Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: Show category/sub-category events on calendar category header (add eventsFromCategory parameter in categorySetting of admin plugin settings) #198

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/controllers/discourse_post_event/events_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def ics_request?
end

def filtered_events_params
params.permit(:post_id)
params.permit(:post_id, :category_id, :include_subcategories)
end
end
end
3 changes: 2 additions & 1 deletion app/serializers/discourse_post_event/event_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ def post
url: object.post.url,
topic: {
id: object.post.topic.id,
title: object.post.topic.title
title: object.post.topic.title,
category_id: object.post.topic.category_id
}
}
end
Expand Down
114 changes: 103 additions & 11 deletions assets/javascripts/initializers/discourse-calendar.js.es6
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ function initializeDiscourseCalendar(api) {
browsedCategory.id.toString()
);

// Manage calendar with postId in categorySetting (extension setting)
if (categorySetting && categorySetting.postId) {
$calendarContainer.show();
const postId = categorySetting.postId;
Expand All @@ -79,16 +80,7 @@ function initializeDiscourseCalendar(api) {
);
$calendarContainer.html($spinner);
loadFullCalendar().then(() => {
const options = [`postId=${postId}`];

const optionals = ["weekends", "tzPicker", "defaultView"];
optionals.forEach((optional) => {
if (isPresent(categorySetting[optional])) {
options.push(
`${optional}=${escapeExpression(categorySetting[optional])}`
);
}
});
const options = extractOptionalsCategorySettingOptions([`postId=${postId}`], categorySetting);

const rawCalendar = `[calendar ${options.join(" ")}]\n[/calendar]`;
const cookRaw = cookAsync(rawCalendar);
Expand All @@ -102,6 +94,41 @@ function initializeDiscourseCalendar(api) {
});
});
}

// Manage calendar with eventsFromCategory in categorySetting (extension setting)
if (categorySetting && categorySetting.eventsFromCategory) {
const { eventsFromCategory } = categorySetting;
// Show container
$calendarContainer.show();

// Add a loader
const $spinner = $(
'<div class="calendar"><div class="spinner medium"></div></div>'
);
$calendarContainer.html($spinner);

// Load fullcalendar.io script
loadFullCalendar().then(() => {
const options = extractOptionalsCategorySettingOptions([`eventsFromCategory=${eventsFromCategory}`], categorySetting);

const rawCalendar = `[calendar ${options.join(" ")}]\n[/calendar]`;
// Cooking calendar
const cookRaw = cookAsync(rawCalendar);
// Fetch event from category id
const fetchEvents = ajax(`/discourse-post-event/events.json?category_id=${eventsFromCategory}&include_subcategories=true`);

// Execute cooking and fetch events
Promise.all([cookRaw, fetchEvents]).then((results) => {
const cooked = results[0];
const { events } = results[1];
const $cooked = $(cooked.string);

// Add calendar to DOM
$calendarContainer.html($cooked);
renderCalendarFromCategoryEvents($(".calendar", $cooked), events);
})
});
}
}
});

Expand Down Expand Up @@ -131,6 +158,62 @@ function initializeDiscourseCalendar(api) {
}
);


/**
* Extract optionals options from categorySetting ("calendar categories" in extension settings)
*
* @return array
*/
function extractOptionalsCategorySettingOptions(options, categorySetting) {
const optionals = ["weekends", "tzPicker", "defaultView"];

optionals.forEach((optional) => {
if (isPresent(categorySetting[optional])) {
options.push(
`${optional}=${escapeExpression(categorySetting[optional])}`
);
}
});

return options;
}

/**
* Render a calendar with event from a category
*
* @returns Void
*/
function renderCalendarFromCategoryEvents($calendar, events) {

$calendar = $calendar.empty();
const timezone = _getTimeZone($calendar, api.getCurrentUser());
// Instantiate fullcalendar.io
const calendar = _buildCalendar($calendar, timezone);

calendar.render();
_setupTimezonePicker(calendar, timezone);

// Iterate events
events.forEach(rawEvent => {
const event = {
title: rawEvent.name || rawEvent.post.topic.title,
start: rawEvent.starts_at,
end: rawEvent.ends_at,
extendedProps: {
postNumber: rawEvent.post.post_number,
postUrl: rawEvent.post.url,
}
};

// Add a events
calendar.addEvent(event);

// Bind click, mouse over...
bindMouseEvents(calendar, event);

});
}

function render($calendar, post, siteSettings) {
$calendar = $calendar.empty();

Expand Down Expand Up @@ -306,7 +389,16 @@ function initializeDiscourseCalendar(api) {
);
}

calendar.setOption("eventClick", ({ event, jsEvent }) => {
bindMouseEvents(calendar, event);
}

/**
* Bind mouseEvents (HTML DOM)
*
* @returns Void
*/
function bindMouseEvents(calendar, event) {
calendar.setOption("eventClick", ({ event, jsEvent }) => {
hidePopover(jsEvent);
const { htmlContent, postNumber, postUrl } = event.extendedProps;

Expand Down