Skip to content
Snippets Groups Projects
Commit bfe7f813 authored by Konrad Mohrfeldt's avatar Konrad Mohrfeldt :koala:
Browse files

feat: hide event content if it wouldn’t be legible anyway

refs #151
parent 8b40e1d7
No related branches found
No related tags found
No related merge requests found
......@@ -211,6 +211,8 @@
</template>
<script>
import { parseISO } from 'date-fns'
import { h } from 'vue'
import { mapGetters } from 'vuex'
import FullCalendar from '@fullcalendar/vue3'
......@@ -227,7 +229,12 @@ import playlist from '@/mixins/playlist'
import ServerErrors from '@/components/ServerErrors.vue'
import { getISODateString } from '@/utilities'
import PageHeader from '@/components/PageHeader.vue'
import { getClosestSlot, getNextAvailableSlot, sanitizeHTML } from '@/util'
import {
calculateDurationSeconds,
getClosestSlot,
getNextAvailableSlot,
sanitizeHTML,
} from '@/util'
import SafeHTML from '@/components/generic/SafeHTML'
export default {
......@@ -341,6 +348,37 @@ export default {
allDaySlot: false,
editable: false,
nowIndicator: true,
eventContent({ event, timeText }) {
// The eventContent function doesn’t quite seem to work like documented in the fullcalendar docs:
// * the slot is broken because it doesn’t receive a context object ('arg' is undefined)
// * the Preact createElement/h function that is passed as the second argument to this function
// doesn’t render anything
// * returning { html: '<i>hello</i>' } doesn’t render anything
// * returning { domNodes: [(() => { const i = document.createElement('i'); i.textContent = 'hello'; return i })()] }
// doesn’t render anything
//
// Instead, this comment [1] mentions that one should use the Vue createElement/h function.
// Surprisingly this works.
//
// It is unclear to me why all these (documented) options fail. One major difference is that we run Vue 3 in
// Vue 2 compat mode which might be a source of errors.
//
// [1]: https://github.com/fullcalendar/fullcalendar/issues/7175#issuecomment-1409519357
const { durationMinutes, title } = event.extendedProps
// don’t render any content if it would be crammed anyway
const content =
durationMinutes > slotDurationMinutes
? [
h('div', { class: 'fc-event-time' }, timeText),
h('div', { class: 'fc-event-title-container' }, [
h('div', { class: 'fc-event-title fc-sticky' }, title),
]),
]
: []
return h('div', { class: 'fc-event-main-frame' }, content)
},
datesSet: (view) => {
if (
this.currentStart?.toISOString?.() !== view.start.toISOString() ||
......@@ -802,6 +840,8 @@ export default {
start: timeslot.start,
end: timeslot.end,
title,
durationMinutes:
calculateDurationSeconds(parseISO(timeslot.start), parseISO(timeslot.end)) / 60,
},
})
}
......
......@@ -75,6 +75,10 @@ export function getNextAvailableSlot(slotDurationMinutes: number, date?: Date):
return new Date(nextSlotTimestamp)
}
export function calculateDurationSeconds(start: Date, end: Date): number {
return Math.abs(end.getTime() - start.getTime()) / 1000
}
export function sanitizeHTML(
html: string,
preset?: 'inline-noninteractive' | 'safe-html' | 'strip',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment