From 212396a8ede9777a90b0930e6a468e925ae01048 Mon Sep 17 00:00:00 2001 From: Hangzhi Yu <hangzhi@protonmail.com> Date: Fri, 17 Jan 2025 16:22:34 +0100 Subject: [PATCH] Add expand functionality for all day calendar events in calendar --- .../frontend/components/calendar/Calendar.vue | 84 ++++++++++++++++++- aleksis/core/frontend/css/global.scss | 5 ++ aleksis/core/frontend/messages/en.json | 3 +- 3 files changed, 90 insertions(+), 2 deletions(-) diff --git a/aleksis/core/frontend/components/calendar/Calendar.vue b/aleksis/core/frontend/components/calendar/Calendar.vue index 5f5c44c9c..d8fcdfe39 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 6bbdf6e47..135927a85 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 aa81486df..e68e9a294 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.", -- GitLab