FEATURE: site setting to include expired events on calendar views (#499)
* FEATURE: site setting to include expired events on calendar views Adds a new site setting to include expired events on calendar views (Upcoming Events and Category Calendar). Past events are displayed with the configured color (from the category or from the "Map events to color" site setting) as text and border colors instead of the background.
This commit is contained in:
parent
f69229a88d
commit
becfe9b2ad
|
|
@ -119,7 +119,7 @@ module DiscoursePostEvent
|
|||
private
|
||||
|
||||
def filtered_events_params
|
||||
params.permit(:post_id, :category_id, :include_subcategories)
|
||||
params.permit(:post_id, :category_id, :include_subcategories, :include_expired)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@ import DiscoursePostEventAdapter from "./discourse-post-event-adapter";
|
|||
|
||||
export default DiscoursePostEventAdapter.extend({
|
||||
pathFor(store, type, findArgs) {
|
||||
let path =
|
||||
const path =
|
||||
this.basePath(store, type, findArgs) +
|
||||
underscore(store.pluralize(this.apiNameFor(type)));
|
||||
return this.appendQueryParams(path, findArgs) + ".json";
|
||||
return this.appendQueryParams(`${path}.json`, findArgs);
|
||||
},
|
||||
|
||||
apiNameFor() {
|
||||
|
|
|
|||
|
|
@ -127,6 +127,12 @@ export default Component.extend({
|
|||
`#${this.site.categoriesById[category_id]?.color}`;
|
||||
}
|
||||
|
||||
let borderColor, textColor;
|
||||
if (moment(ends_at || starts_at).isBefore(moment())) {
|
||||
borderColor = textColor = backgroundColor;
|
||||
backgroundColor = undefined;
|
||||
}
|
||||
|
||||
this._calendar.addEvent({
|
||||
title: formatEventName(event),
|
||||
start: starts_at,
|
||||
|
|
@ -134,6 +140,8 @@ export default Component.extend({
|
|||
allDay: !isNotFullDayEvent(moment(starts_at), moment(ends_at)),
|
||||
url: getURL(`/t/-/${post.topic.id}/${post.post_number}`),
|
||||
backgroundColor,
|
||||
borderColor,
|
||||
textColor,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -177,9 +177,16 @@ function initializeDiscourseCalendar(api) {
|
|||
},
|
||||
}
|
||||
);
|
||||
const loadEvents = ajax(
|
||||
`/discourse-post-event/events.json?category_id=${browsedCategory.id}&include_subcategories=true`
|
||||
);
|
||||
const params = {
|
||||
category_id: browsedCategory.id,
|
||||
include_subcategories: true,
|
||||
};
|
||||
if (siteSettings.include_expired_events_on_calendar) {
|
||||
params.include_expired = true;
|
||||
}
|
||||
const loadEvents = ajax(`/discourse-post-event/events.json`, {
|
||||
data: params,
|
||||
});
|
||||
|
||||
Promise.all([loadEvents]).then((results) => {
|
||||
const events = results[0];
|
||||
|
|
@ -210,6 +217,12 @@ function initializeDiscourseCalendar(api) {
|
|||
`#${site.categoriesById[category_id]?.color}`;
|
||||
}
|
||||
|
||||
let borderColor, textColor;
|
||||
if (moment(ends_at || starts_at).isBefore(moment())) {
|
||||
borderColor = textColor = backgroundColor;
|
||||
backgroundColor = undefined;
|
||||
}
|
||||
|
||||
fullCalendar.addEvent({
|
||||
title: formatEventName(event),
|
||||
start: starts_at,
|
||||
|
|
@ -217,6 +230,8 @@ function initializeDiscourseCalendar(api) {
|
|||
allDay: !isNotFullDayEvent(moment(starts_at), moment(ends_at)),
|
||||
url: getURL(`/t/-/${post.topic.id}/${post.post_number}`),
|
||||
backgroundColor,
|
||||
borderColor,
|
||||
textColor,
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,9 @@ export default Route.extend({
|
|||
}),
|
||||
|
||||
model(params) {
|
||||
if (this.siteSettings.include_expired_events_on_calendar) {
|
||||
params.include_expired = true;
|
||||
}
|
||||
return this.store.findAll("discourse-post-event-event", params);
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ en:
|
|||
disable_resorting_on_categories_enabled: "Allow categories to disable the ability for users to sort on the event category."
|
||||
calendar_automatic_holidays_enabled: "Automatically set holiday status based on a users region (note: you can disable specific automatic holidays in plugin settings)"
|
||||
sidebar_show_upcoming_events: "Show upcoming events link in the sidebar under 'More'."
|
||||
include_expired_events_on_calendar: "Include past/expired events on Category Calendar and Upcoming Events views."
|
||||
discourse_calendar:
|
||||
invite_user_notification: "%{username} invited you to: %{description}"
|
||||
calendar_must_be_in_first_post: "Calendar tag can only be used in first post of a topic."
|
||||
|
|
|
|||
|
|
@ -110,3 +110,6 @@ discourse_calendar:
|
|||
client: true
|
||||
default: "[]"
|
||||
json_schema: DiscourseCalendar::SiteSettings::MapEventTagColorsJsonSchema
|
||||
include_expired_events_on_calendar:
|
||||
default: false
|
||||
client: true
|
||||
|
|
|
|||
|
|
@ -7,33 +7,29 @@ module DiscoursePostEvent
|
|||
topics = listable_topics(guardian)
|
||||
pms = private_messages(user)
|
||||
|
||||
dates_join = <<~SQL
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
finished_at,
|
||||
event_id,
|
||||
starts_at,
|
||||
ROW_NUMBER() OVER (PARTITION BY event_id ORDER BY finished_at DESC NULLS FIRST) as row_num
|
||||
FROM discourse_calendar_post_event_dates
|
||||
) dcped ON dcped.event_id = discourse_post_event_events.id AND dcped.row_num = 1
|
||||
|
||||
SQL
|
||||
events =
|
||||
DiscoursePostEvent::Event
|
||||
.select("discourse_post_event_events.*, dcped.starts_at")
|
||||
.joins(post: :topic)
|
||||
.merge(Post.secured(guardian))
|
||||
.merge(topics.or(pms).distinct)
|
||||
.joins(
|
||||
"LEFT JOIN discourse_calendar_post_event_dates dcped ON dcped.event_id = discourse_post_event_events.id",
|
||||
)
|
||||
.joins(dates_join)
|
||||
.order("dcped.starts_at ASC")
|
||||
|
||||
if params[:expired]
|
||||
# The second part below makes the query ignore events that have non-expired event-dates
|
||||
events =
|
||||
events.where(
|
||||
"dcped.finished_at IS NOT NULL AND (dcped.ends_at IS NOT NULL AND dcped.ends_at < ?)",
|
||||
Time.now,
|
||||
).where(
|
||||
"discourse_post_event_events.id NOT IN (SELECT DISTINCT event_id FROM discourse_calendar_post_event_dates WHERE event_id = discourse_post_event_events.id AND finished_at IS NULL)",
|
||||
)
|
||||
else
|
||||
events =
|
||||
events.where(
|
||||
"dcped.finished_at IS NULL AND (dcped.ends_at IS NULL OR dcped.ends_at > ?)",
|
||||
Time.now,
|
||||
)
|
||||
end
|
||||
include_expired = params[:include_expired].to_s == "true"
|
||||
|
||||
events = events.where("dcped.finished_at IS NULL") unless include_expired
|
||||
|
||||
events = events.where(id: Array(params[:post_id])) if params[:post_id]
|
||||
|
||||
|
|
|
|||
|
|
@ -122,8 +122,12 @@ describe DiscoursePostEvent::EventFinder do
|
|||
end
|
||||
|
||||
it "returns correct events" do
|
||||
expect(finder.search(current_user, { expired: false })).to eq([current_event, future_event])
|
||||
expect(finder.search(current_user, { expired: true })).to eq([older_event, old_event])
|
||||
expect(finder.search(current_user, { include_expired: false })).to eq(
|
||||
[current_event, future_event],
|
||||
)
|
||||
expect(finder.search(current_user, { include_expired: true })).to eq(
|
||||
[older_event, old_event, current_event, future_event],
|
||||
)
|
||||
end
|
||||
|
||||
context "when a past event has been edited to be in the future" do
|
||||
|
|
@ -138,10 +142,12 @@ describe DiscoursePostEvent::EventFinder do
|
|||
end
|
||||
|
||||
it "returns correct events" do
|
||||
expect(finder.search(current_user, { expired: false })).to eq(
|
||||
expect(finder.search(current_user, { include_expired: false })).to eq(
|
||||
[current_event, future_event],
|
||||
)
|
||||
expect(finder.search(current_user, { expired: true })).to eq([older_event, old_event])
|
||||
expect(finder.search(current_user, { include_expired: true })).to eq(
|
||||
[older_event, old_event, current_event, future_event],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -157,10 +163,12 @@ describe DiscoursePostEvent::EventFinder do
|
|||
end
|
||||
|
||||
it "returns correct events" do
|
||||
expect(finder.search(current_user, { expired: false })).to eq(
|
||||
expect(finder.search(current_user, { include_expired: false })).to eq(
|
||||
[current_event, future_event],
|
||||
)
|
||||
expect(finder.search(current_user, { expired: true })).to eq([older_event, old_event])
|
||||
expect(finder.search(current_user, { include_expired: true })).to eq(
|
||||
[older_event, current_event, future_event, old_event],
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -227,6 +227,14 @@ module DiscoursePostEvent
|
|||
Fabricate(:post, post_number: 1, topic: Fabricate(:topic, category: subcategory)),
|
||||
)
|
||||
end
|
||||
fab!(:event_3) do
|
||||
Fabricate(
|
||||
:event,
|
||||
post: Fabricate(:post, post_number: 1, topic: Fabricate(:topic, category: category)),
|
||||
original_starts_at: 10.days.ago,
|
||||
original_ends_at: 9.days.ago,
|
||||
)
|
||||
end
|
||||
|
||||
it "can filter the event by category" do
|
||||
get "/discourse-post-event/events.json?category_id=#{category.id}"
|
||||
|
|
@ -267,6 +275,21 @@ module DiscoursePostEvent
|
|||
"is_standalone",
|
||||
)
|
||||
end
|
||||
|
||||
it "includes expired events when param provided" do
|
||||
get "/discourse-post-event/events.json?category_id=#{category.id}&include_subcategories=true&include_expired=true"
|
||||
|
||||
expect(response.status).to eq(200)
|
||||
events = response.parsed_body["events"]
|
||||
expect(events.length).to eq(3)
|
||||
expect(events).to match_array(
|
||||
[
|
||||
hash_including("id" => event_1.id),
|
||||
hash_including("id" => event_2.id),
|
||||
hash_including("id" => event_3.id),
|
||||
],
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in New Issue