feature(Calendar): keeps track of the selected Event in a shared state and highlights the selected Event over different calendar views

This commit is contained in:
SimonGschnell
2024-11-15 12:52:24 +01:00
parent 65d0e89f06
commit fdcef8bdab
7 changed files with 47 additions and 25 deletions
+7 -2
View File
@@ -129,8 +129,13 @@ const app = Vue.createApp({
<hr>
<lv-modal v-if="currentlySelectedEvent" :event="currentlySelectedEvent" ref="lvmodal" />
<fhc-calendar :initial-date="currentDay" @change:range="updateRange" :events="events" initial-mode="week" show-weeks @select:day="selectDay" v-model:minimized="minimized">
<template #weekPage="{event,day}">
<div @click="showModal(event?.orig)" type="button" class="fhc-entry border border-secondary border d-flex flex-column align-items-center justify-content-evenly h-100">
<template #monthPage="{event,day,isSelected}">
<span class="fhc-entry" :class="{'selectedEvent':isSelected}" style="color:white" :style="{'background-color': event.color}">
{{event.topic}}
</span>
</template>
<template #weekPage="{event,day,isSelected}">
<div @click="showModal(event?.orig)" type="button" :class="{'selectedEvent':isSelected}" class="fhc-entry border border-secondary border d-flex flex-column align-items-center justify-content-evenly h-100">
<span>{{event?.orig.topic}}</span>
<span v-for="lektor in event?.orig.lektor">{{lektor.kurzbz}}</span>
<span>{{event?.orig.ort_kurzbz}}</span>
+9 -3
View File
@@ -34,6 +34,8 @@ export default {
eventsAreNull: Vue.computed(() => this.events === null),
classHeader: this.classHeader,
mode: Vue.computed(()=>this.mode),
selectedEvent: Vue.computed(() => this.selectedEvent),
setSelectedEvent: (event)=>{this.selectedEvent = event;},
};
},
props: {
@@ -91,7 +93,8 @@ export default {
currMode: null,
date: new CalendarDate(),
focusDate: new CalendarDate(),
size: 0
size: 0,
selectedEvent:null,
}
},
computed: {
@@ -209,8 +212,11 @@ export default {
template: /*html*/`
<div ref="container" class="fhc-calendar card h-100" :class="sizeClass">
<component :is="'calendar-' + mode" @updateMode="mode = $event" @change:range="$emit('change:range',$event)" @input="handleInput" >
<template #weekPage="{event,day}">
<slot name="weekPage" :event="event" :day="day"></slot>
<template #monthPage="{event,day,isSelected}">
<slot name="monthPage" :event="event" :day="day" :isSelected="isSelected"></slot>
</template>
<template #weekPage="{event,day,isSelected}">
<slot name="weekPage" :event="event" :day="day" :isSelected="isSelected"></slot>
</template>
<template #dayPage="{event,day}">
<slot name="dayPage" :event="event" :day="day"></slot>
+6 -8
View File
@@ -15,7 +15,6 @@ export default {
hourPosition: null,
hourPositionTime: null,
lvMenu:null,
selectedEvent: null,
}
},
inject: [
@@ -28,6 +27,8 @@ export default {
'isSliding',
'calendarScrollTop',
'calendarClientHeight',
'setSelectedEvent',
'selectedEvent',
],
props: {
year: Number,
@@ -42,13 +43,12 @@ export default {
watch:{
eventsPerDayAndHour:{
handler(newEvents) {
if (newEvents[this.day.toDateString()]?.events.length > 0) {
// if no event is selected, select the first event of the day
if (this.selectedEvent == null && newEvents[this.day.toDateString()]?.events.length > 0) {
let events = newEvents[this.day.toDateString()]?.events;
if (Array.isArray(events) && events.length > 0) {
this.selectedEvent = events[0].orig;
this.setSelectedEvent(events[0].orig);
}
} else {
this.selectedEvent = null;
}
},
immediate: true
@@ -129,7 +129,7 @@ export default {
methods: {
eventClick(evt) {
let event = evt.orig;
this.selectedEvent = event;
this.setSelectedEvent(event);
this.$emit('input', event);
},
calcHourPosition(event) {
@@ -217,11 +217,9 @@ export default {
<p>this is a placeholder which means that no template was passed to the Calendar Page slot</p>
</slot>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
+5 -1
View File
@@ -63,7 +63,11 @@ export default {
<div class="fhc-calendar-month">
<calendar-header :title="title" @prev="prev" @next="next" @updateMode="$emit('updateMode', $event)" @click="$emit('updateMode', 'months')" />
<calendar-pane ref="pane" v-slot="slot" @slid="paneChanged">
<calendar-month-page :year="focusDate.y" :month="focusDate.m+slot.offset" @updateMode="$emit('updateMode', $event)" @page:back="prev" @page:forward="next" @input="selectDay" />
<calendar-month-page :year="focusDate.y" :month="focusDate.m+slot.offset" @updateMode="$emit('updateMode', $event)" @page:back="prev" @page:forward="next" @input="selectDay" >
<template #monthPage="{event,day,isSelected}">
<slot name="monthPage" :event="event" :day="day" :isSelected="isSelected"></slot>
</template>
</calendar-month-page>
</calendar-pane>
</div>`
}
+8 -5
View File
@@ -14,6 +14,8 @@ export default {
'events',
'showWeeks',
'noWeekView',
'selectedEvent',
'setSelectedEvent',
],
props: {
year: Number,
@@ -75,13 +77,12 @@ export default {
clickEvent(day,week) {
if(!this.noWeekView)
{
//this.changeToWeek(week);
this.changeToDay(day);
}
this.selectDay(day);
}
},
template: `
template: /*html*/`
<div class="fhc-calendar-month-page" :class="{'show-weeks': showWeeks}">
<div v-if="showWeeks" class=" bg-light fw-bold border-top border-bottom text-center"></div>
<div v-for="day in weeks[0].days" :key="day" class="bg-light fw-bold border-top border-bottom text-center">
@@ -92,9 +93,11 @@ export default {
<a href="#" @click.prevent="clickEvent(day,week)" @mouseover="highlight(week,day)" @mouseleave="highlightedWeek = null; highlightedDay = null" v-for="day in week.days" :key="day" :class="{'fhc-calendar-month-page-day-highlight': isHighlighted(week, day)}" class="fhc-calendar-month-page-day text-decoration-none overflow-hidden" :class="{active:date.compare(day),'opacity-50':day.getMonth() != month}" >
<span class="no">{{day.getDate()}}</span>
<span v-if="events[day.toDateString()] && events[day.toDateString()].length" class="events">
<span v-for="event in events[day.toDateString()]" :key="event.id" style="color:white" :style="{'background-color': event.color}">
{{event.topic}}
</span>
<div @click="setSelectedEvent(event);" v-for="event in events[day.toDateString()]" :key="event.id" >
<slot name="monthPage" :event="event" :day="day" :isSelected="event == selectedEvent">
<p>this is a placeholder which means that no template was passed to the Calendar Page slot</p>
</slot>
</div>
</span>
</a>
</template>
+2 -2
View File
@@ -43,8 +43,8 @@ export default {
<calendar-header :title="title" @prev="prev" @next="next" @updateMode="$emit('updateMode', $event)" @click="$emit('updateMode', 'weeks')"/>
<calendar-pane ref="pane" v-slot="slot" @slid="paneChanged">
<calendar-week-page :year="focusDate.y" :week="focusDate.w+slot.offset" @updateMode="$emit('updateMode', $event)" @page:back="prev" @page:forward="next" @input="selectEvent" >
<template #weekPage="{event,day}">
<slot name="weekPage" :event="event" :day="day" ></slot>
<template #weekPage="{event,day,isSelected}">
<slot name="weekPage" :event="event" :day="day" :isSelected="isSelected"></slot>
</template>
</calendar-week-page>
</calendar-pane>
+10 -4
View File
@@ -16,7 +16,9 @@ export default {
'size',
'events',
'noMonthView',
'isSliding'
'isSliding',
'selectedEvent',
'setSelectedEvent'
],
props: {
year: Number,
@@ -26,7 +28,7 @@ export default {
'updateMode',
'page:back',
'page:forward',
'input'
'input',
],
computed: {
hours(){
@@ -138,6 +140,10 @@ export default {
},
dateToMinutesOfDay(day) {
return Math.floor(((day.getHours()-7) * 60 + day.getMinutes()) / this.smallestTimeFrame) + 1;
},
weekPageClick(event) {
this.setSelectedEvent(event);
$emit('input', event)
}
},
mounted() {
@@ -164,8 +170,8 @@ export default {
<div v-for="hour in hours" style="min-height:100px" :key="hour" class="text-muted text-end small" :ref="'hour' + hour">{{hour}}:00</div>
</div>
<div v-for="day in eventsPerDayAndHour" :key="day" class=" day border-start" :style="{'grid-template-columns': 'repeat(' + day.lanes + ', 1fr)', 'grid-template-rows': 'repeat(' + (hours.length * 60 / smallestTimeFrame) + ', 1fr)'}">
<div :style="{'background-color':event.orig.color}" class="mx-2 small rounded overflow-hidden " @click.prevent="$emit('input', event.orig)" :style="{'z-index':1,'grid-column-start': 1+(event.lane-1)*day.lanes/event.maxLane, 'grid-column-end': 1+event.lane*day.lanes/event.maxLane, 'grid-row-start': dateToMinutesOfDay(event.start), 'grid-row-end': dateToMinutesOfDay(event.end) ,'--test': dateToMinutesOfDay(event.end)}" v-for="event in day.events" :key="event">
<slot name="weekPage" :event="event" :day="day">
<div :style="{'background-color':event.orig.color}" class="mx-2 small rounded overflow-hidden " @click.prevent="weekPageClick(event.orig)" :style="{'z-index':1,'grid-column-start': 1+(event.lane-1)*day.lanes/event.maxLane, 'grid-column-end': 1+event.lane*day.lanes/event.maxLane, 'grid-row-start': dateToMinutesOfDay(event.start), 'grid-row-end': dateToMinutesOfDay(event.end) ,'--test': dateToMinutesOfDay(event.end)}" v-for="event in day.events" :key="event">
<slot name="weekPage" :event="event" :day="day" :isSelected="event.orig == selectedEvent" >
<p>this is a placeholder which means that no template was passed to the Calendar Page slot</p>
</slot>
</div>