diff --git a/assets/javascripts/discourse/components/upcoming-events-list.gjs b/assets/javascripts/discourse/components/upcoming-events-list.gjs index f2281bb15..1918077d8 100644 --- a/assets/javascripts/discourse/components/upcoming-events-list.gjs +++ b/assets/javascripts/discourse/components/upcoming-events-list.gjs @@ -17,6 +17,15 @@ export const DEFAULT_TIME_FORMAT = "LT"; const DEFAULT_UPCOMING_DAYS = 180; const DEFAULT_COUNT = 8; +function addToResult(date, item, result) { + const day = date.date(); + const monthKey = date.format("YYYY-MM"); + + result[monthKey] = result[monthKey] ?? {}; + result[monthKey][day] = result[monthKey][day] ?? []; + result[monthKey][day].push(item); +} + export default class UpcomingEventsList extends Component { @service appEvents; @service siteSettings; @@ -108,17 +117,22 @@ export default class UpcomingEventsList extends Component { groupByMonthAndDay(data) { return data.reduce((result, item) => { - const date = new Date(item.starts_at); - const year = date.getFullYear(); - const month = date.getMonth() + 1; - const day = date.getDate(); - - const monthKey = `${year}-${month}`; - - result[monthKey] = result[monthKey] ?? {}; - result[monthKey][day] = result[monthKey][day] ?? []; - - result[monthKey][day].push(item); + const startDate = moment(item.starts_at); + const endDate = item.ends_at ? moment(item.ends_at) : null; + const today = moment(); + + if (!endDate) { + addToResult(startDate, item, result); + return result; + } + + while (startDate.isSameOrBefore(endDate, "day")) { + if (startDate.isAfter(today)) { + addToResult(startDate, item, result); + } + + startDate.add(1, "day"); + } return result; }, {}); diff --git a/test/javascripts/integration/components/upcoming-events-list-test.gjs b/test/javascripts/integration/components/upcoming-events-list-test.gjs index e82546076..06fb61268 100644 --- a/test/javascripts/integration/components/upcoming-events-list-test.gjs +++ b/test/javascripts/integration/components/upcoming-events-list-test.gjs @@ -27,6 +27,7 @@ class RouterStub extends Service { const today = "2100-02-01T08:00:00"; const tomorrowAllDay = "2100-02-02T00:00:00"; const nextMonth = "2100-03-02T08:00:00"; +const nextWeek = "2100-02-09T08:00:00"; module("Integration | Component | upcoming-events-list", function (hooks) { setupRenderingTest(hooks); @@ -134,6 +135,34 @@ module("Integration | Component | upcoming-events-list", function (hooks) { ); }); + test("with multi-day events, standard formats", async function (assert) { + pretender.get("/discourse-post-event/events", multiDayEventResponseHandler); + + await render(); + + this.appEvents.trigger("page:changed", { url: "/" }); + + await waitFor(".loading-container .spinner", { count: 0 }); + + assert.deepEqual( + [...queryAll(".upcoming-events-list__event-name")].map( + (el) => el.innerText + ), + [ + "Awesome Multiday Event", + "Awesome Multiday Event", + "Awesome Multiday Event", + "Awesome Multiday Event", + "Awesome Multiday Event", + "Awesome Multiday Event", + "Awesome Multiday Event", + "Awesome Multiday Event", + ], + + "it displays the multiday event on all scheduled dates" + ); + }); + test("with events, view-all navigation", async function (assert) { pretender.get("/discourse-post-event/events", twoEventsResponseHandler); @@ -370,3 +399,37 @@ function twoEventsResponseHandler({ queryParams }) { return response({ events }); } + +function multiDayEventResponseHandler({ queryParams }) { + let events = [ + { + id: 67503, + starts_at: tomorrowAllDay, + ends_at: nextWeek, + timezone: "Asia/Calcutta", + post: { + id: 67501, + post_number: 1, + url: "/t/this-is-an-event/18451/1", + topic: { + id: 18449, + title: "This is a multiday event", + }, + }, + name: "Awesome Multiday Event", + category_id: 1, + }, + ]; + + if (queryParams.limit) { + events.splice(queryParams.limit); + } + + if (queryParams.before) { + events = events.filter((event) => { + return moment(event.starts_at).isBefore(queryParams.before); + }); + } + + return response({ events }); +}