diff --git a/aleksis/core/frontend/components/calendar/Calendar.vue b/aleksis/core/frontend/components/calendar/Calendar.vue index 5f5c44c9ced529606f9d621294a30d42cf47e5d4..d8fcdfe39a6e5f46568315c94c5b32cd3bdaf112 100644 --- a/aleksis/core/frontend/components/calendar/Calendar.vue +++ b/aleksis/core/frontend/components/calendar/Calendar.vue @@ -40,6 +40,44 @@ :calendar-type="internalCalendarType" /> </template> + <template + v-if="Object.keys(daysWithHiddenEvents).length" + #interval-header + > + <div + v-if=" + !internalCalendarType === 'day' || + Object.keys(daysWithHiddenEvents).includes(internalCalendarFocus) + " + class="d-flex justify-center align-end" + :style="{ height: '100%' }" + > + <v-btn + icon + class="ma-2" + @click="showAllAllDayEvents = !showAllAllDayEvents" + > + <v-icon>{{ showAllAllDayEventsButtonIcon }}</v-icon> + </v-btn> + </div> + </template> + <template #day-header="{ date }"> + <template + v-if=" + Object.keys(daysWithHiddenEvents).includes(date) && + !showAllAllDayEvents + " + > + <v-spacer /> + <div + class="v-event-more ml-1" + v-ripple + @click="showAllAllDayEvents = true" + > + {{ $tc("calendar.more_events", daysWithHiddenEvents[date]) }} + </div> + </template> + </template> </v-calendar> <component v-if="selectedEvent" @@ -65,6 +103,8 @@ import { import { gqlCalendar, calendarDaysPreference } from "./calendar.graphql"; +import { Interval } from "luxon"; + export default { name: "Calendar", props: { @@ -104,6 +144,11 @@ export default { required: false, default: "current", }, + maxAllDayEvents: { + type: Number, + required: false, + default: 5, + }, }, data() { return { @@ -139,6 +184,9 @@ export default { daysOfWeek: [1, 2, 3, 4, 5, 6, 0], }, }, + + showAllAllDayEvents: false, + daysWithHiddenEvents: {}, }; }, emits: ["changeCalendarType", "changeCalendarFocus", "selectEvent"], @@ -164,7 +212,7 @@ export default { }; }, events() { - return this.calendar.calendarFeeds + let events = this.calendar.calendarFeeds .filter((c) => this.calendarFeeds.map((cf) => cf.name).includes(c.name)) .flatMap((cf) => cf.events.map((event) => { @@ -184,6 +232,34 @@ export default { }; }), ); + if (this.internalCalendarType === "month" || this.showAllAllDayEvents) { + return events; + } + + let dateFullEventCount = {}; + this.clearDaysWithHiddenEvents(); + + return events.filter((event) => { + if (!event.allDay) { + return true; + } + const start = event.startDateTime; + dateFullEventCount[start] = (dateFullEventCount[start] || 0) + 1; + const show = dateFullEventCount[start] <= this.maxAllDayEvents; + if (!show) { + const dateInterval = Interval.fromDateTimes( + start, + event.endDateTime.endOf("day"), + ) + .splitBy({ day: 1 }) + .map((date) => date.start.toISODate()); + for (const date of dateInterval) { + this.daysWithHiddenEvents[date] = + (this.daysWithHiddenEvents[date] || 0) + 1; + } + } + return show; + }); }, paramsForSend() { if (this.params !== null) { @@ -251,6 +327,9 @@ export default { return this.personByIdOrMe.preferences.daysOfWeek; }, + showAllAllDayEventsButtonIcon() { + return this.showAllAllDayEvents ? "mdi-chevron-up" : "mdi-chevron-down"; + }, }, watch: { params(newParams) { @@ -526,6 +605,9 @@ export default { // TODO: is this destroyed when unloading? setInterval(() => this.cal.updateTimes(), 60 * 1000); }, + clearDaysWithHiddenEvents() { + this.daysWithHiddenEvents = {}; + }, }, mounted() { this.ready = true; diff --git a/aleksis/core/frontend/css/global.scss b/aleksis/core/frontend/css/global.scss index 6bbdf6e47d9cef354efcb3fa46eedca16e0b9483..135927a8572c1c38f805eab2027ad7a9bc58224d 100644 --- a/aleksis/core/frontend/css/global.scss +++ b/aleksis/core/frontend/css/global.scss @@ -39,3 +39,8 @@ h6, .full-width { width: 100%; } + +.v-calendar-daily_head-day { + display: flex; + flex-direction: column; +} diff --git a/aleksis/core/frontend/messages/en.json b/aleksis/core/frontend/messages/en.json index aa81486df08ba090aeb0dcc55405307d0531bd55..e68e9a2946968fe3cf3ac64eeab1ef377cb25f26 100644 --- a/aleksis/core/frontend/messages/en.json +++ b/aleksis/core/frontend/messages/en.json @@ -134,7 +134,8 @@ "my_calendars": "My Calendars", "select": "Select calendars", "today": "Today", - "week": "Week" + "week": "Week", + "more_events": "{n} more" }, "celery_progress": { "error_message": "The operation couldn't be finished successfully.",