mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 20:29:29 +00:00
feature(Calendar Tagesansicht): Calender wird ausgegraut wenn keine LVs an diesen Tag vorhanden sind
This commit is contained in:
@@ -68,6 +68,21 @@
|
||||
box-shadow: 0 0 0 1px #dee2e6 !important;
|
||||
}
|
||||
|
||||
.fhc-calendar-no-events-overlay{
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.fhc-calendar-no-events-overlay::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin:auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: linear-gradient(120deg, white, gray );
|
||||
opacity: .7;
|
||||
}
|
||||
.fhc-calendar-day-page {
|
||||
/*aspect-ratio: 7/6;*/
|
||||
min-height: 0;
|
||||
|
||||
@@ -26,6 +26,7 @@ export default {
|
||||
focusDate: this.focusDate,
|
||||
size: Vue.computed({ get: () => this.size, set: v => this.size = v }),
|
||||
events: Vue.computed(() => this.eventsPerDay),
|
||||
filteredEvents: Vue.computed(() => this.filteredEvents),
|
||||
minimized: Vue.computed({ get: () => this.minimized, set: v => this.$emit('update:minimized', v) }),
|
||||
showWeeks: this.showWeeks,
|
||||
noMonthView: this.noMonthView,
|
||||
@@ -126,31 +127,46 @@ export default {
|
||||
},
|
||||
// returns the hour of the earliest event, used to scroll to the events in the calendar (week / day view)
|
||||
scrollTime: function () {
|
||||
if (this.events && Array.isArray(this.events) && this.events.length > 0) {
|
||||
let filteredEvents = this.events.filter(event => {
|
||||
// week view filters the elements only for the same week
|
||||
let eventDate = new CalendarDate(new Date(event.datum));
|
||||
if(this.mode == 'week'){
|
||||
return this.focusDate.w == eventDate.w;
|
||||
}
|
||||
// day view filters the elements for the same day and the same week
|
||||
else if(this.mode == 'day'){
|
||||
|
||||
return this.focusDate.d == eventDate.d && this.focusDate.w == eventDate.w;
|
||||
}
|
||||
})
|
||||
// return the first beginning time of the filtered events
|
||||
if(filteredEvents.length > 0)
|
||||
if(this.filteredEvents && Array.isArray(this.filteredEvents) && this.filteredEvents.length > 0)
|
||||
{
|
||||
return parseInt(filteredEvents.sort((a, b) => parseInt(a.beginn) - parseInt(b.beginn))[0].beginn);
|
||||
return parseInt(this.filteredEvents.sort((a, b) => parseInt(a.beginn) - parseInt(b.beginn))[0].beginn);
|
||||
}
|
||||
// if there is not filtered event that matches the current week
|
||||
// there is no event that matches the current view mode constraints
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
},
|
||||
// filters the events based on the current calendar view mode
|
||||
// week view - filter events based on their week
|
||||
// day view - filter events based on their day and week
|
||||
// month view - does not filter the events
|
||||
filteredEvents: function(){
|
||||
if (this.events && Array.isArray(this.events) && this.events.length > 0) {
|
||||
let filteredEvents = this.events.filter(event => {
|
||||
let eventDate = new CalendarDate(new Date(event.datum));
|
||||
if (this.mode == 'week')
|
||||
{
|
||||
// week view filters the elements only for the same week
|
||||
return this.focusDate.w == eventDate.w;
|
||||
}
|
||||
else if (this.mode == 'day')
|
||||
{
|
||||
// day view filters the elements for the same day and the same week
|
||||
return this.focusDate.d == eventDate.d && this.focusDate.w == eventDate.w;
|
||||
}
|
||||
else
|
||||
{
|
||||
// returns all the events, does not filter the events
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
return filteredEvents;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
},
|
||||
@@ -190,7 +206,7 @@ export default {
|
||||
|
||||
},
|
||||
template: /*html*/`
|
||||
<div ref="container" class="fhc-calendar card" :class="sizeClass">
|
||||
<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>
|
||||
@@ -198,6 +214,9 @@ export default {
|
||||
<template #dayPage="{event,day}">
|
||||
<slot name="dayPage" :event="event" :day="day"></slot>
|
||||
</template>
|
||||
<template #minimizedPage="{event,day}">
|
||||
<slot name="minimizedPage" :event="event" :day="day"></slot>
|
||||
</template>
|
||||
</component>
|
||||
</div>`
|
||||
}
|
||||
|
||||
@@ -16,7 +16,10 @@ export default {
|
||||
'size',
|
||||
'events',
|
||||
'noMonthView',
|
||||
'isSliding'
|
||||
'filteredEvents',
|
||||
'isSliding',
|
||||
'calendarScrollTop',
|
||||
'calendarClientHeight',
|
||||
],
|
||||
props: {
|
||||
year: Number,
|
||||
@@ -29,6 +32,9 @@ export default {
|
||||
'input'
|
||||
],
|
||||
computed: {
|
||||
noEventsTextPosition(){
|
||||
return this.calendarScrollTop + 100;
|
||||
},
|
||||
hours() {
|
||||
// returns an array with elements starting at 7 and ending at 24
|
||||
return [...Array(24).keys()].filter(hour => hour >= 7 && hour <= 24);
|
||||
@@ -79,7 +85,7 @@ export default {
|
||||
},
|
||||
smallestTimeFrame() {
|
||||
return [30, 15, 10, 5][this.size];
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
calcHourPosition(event) {
|
||||
@@ -157,19 +163,24 @@ export default {
|
||||
<div v-if="hourPosition" class="position-absolute border-top small" style="pointer-events: none; padding-left:3.5rem; margin-top:-1px;z-index:2;border-color:#00649C !important" :style="{top:hourPosition+'px',left:0,right:0}">
|
||||
<span class="border border-top-0 px-2 bg-white">{{hourPositionTime}}</span>
|
||||
</div>
|
||||
<div class="events">
|
||||
<div class="hours">
|
||||
<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': '1 1fr', 'grid-template-rows': 'repeat(' + (hours.length * 60 / smallestTimeFrame) + ', 1fr)'}">
|
||||
<div :style="{'background-color':event.orig.color}" class="mx-2 border border-dark border-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="dayPage" :event="event" :day="day">
|
||||
<p>this is a placeholder which means that no template was passed to the Calendar Page slot</p>
|
||||
</slot>
|
||||
<div>
|
||||
<h1 v-if="filteredEvents.length==0" class="m-0 text-secondary" ref="noEventsText" :style="{'top':noEventsTextPosition+'px'}" style="position:absolute; left:0; text-align:center; width: 100%; z-index:1">Keine Lehrveranstaltungen</h1>
|
||||
<div class="events" :class="{'fhc-calendar-no-events-overlay':filteredEvents.length==0}">
|
||||
|
||||
<div class="hours">
|
||||
<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': '1 1fr', 'grid-template-rows': 'repeat(' + (hours.length * 60 / smallestTimeFrame) + ', 1fr)'}">
|
||||
<div :style="{'background-color':event.orig.color}" class="mx-2 border border-dark border-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="dayPage" :event="event" :day="day">
|
||||
<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>
|
||||
|
||||
@@ -22,9 +22,10 @@ export default {
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="fhc-calendar-minimized">
|
||||
<div class="fhc-calendar-minimized h-100 d-flex flex-column">
|
||||
<div class="card-header d-grid" :class="classHeader">
|
||||
<button class="btn btn-link link-secondary text-decoration-none" @click="maximize">{{ date.format({dateStyle: ['long','full','full','full'][this.size]}) }}</button>
|
||||
</div>
|
||||
<slot name="minimizedPage"></slot>
|
||||
</div>`
|
||||
}
|
||||
|
||||
@@ -8,11 +8,15 @@ export default {
|
||||
queue: 0,
|
||||
offset: 0,
|
||||
slideAnimation:false,
|
||||
scrollTop:null,
|
||||
clientHeight:null,
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
isSliding: Vue.computed(() => this.slideAnimation),
|
||||
calendarScrollTop: Vue.computed(() =>this.scrollTop),
|
||||
calendarClientHeight: Vue.computed(() => this.clientHeight),
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -21,6 +25,10 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
scrollCalendar(event){
|
||||
this.scrollTop = this.$refs.calendarContainer.scrollTop;
|
||||
this.clientHeight = this.$refs.calendarContainer.clientHeight;
|
||||
},
|
||||
prev() {
|
||||
if (!this.queue--)
|
||||
this.carousel.prev();
|
||||
@@ -53,11 +61,13 @@ export default {
|
||||
interval: false
|
||||
});
|
||||
}
|
||||
this.scrollTop = this.$refs.calendarContainer.scrollTop;
|
||||
this.clientHeight = this.$refs.calendarContainer.clientHeight;
|
||||
},
|
||||
template: `
|
||||
<div ref="carousel" class="calendar-pane carousel slide" @[\`slide.bs.carousel\`]="slide" @[\`slid.bs.carousel\`]="slid" :data-queue="queue">
|
||||
<!--height calc function just for user testing purpose (has to be fixed)-->
|
||||
<div class="carousel-inner " style="height:calc(100vh - 220px); overflow:scroll">
|
||||
<div @scroll="scrollCalendar" ref="calendarContainer" class="carousel-inner " style="height:calc(100vh - 220px); overflow:scroll">
|
||||
<div v-for="i in [...Array(3).keys()]" :key="i" class="carousel-item">
|
||||
<slot :index="i" :offset="offsets[i]" />
|
||||
</div>
|
||||
|
||||
@@ -160,25 +160,29 @@ export default {
|
||||
<div class="dashboard-widget-stundenplan d-flex flex-column h-100">
|
||||
<lv-modal v-if="selectedEvent" ref="lvmodal" :event="selectedEvent" />
|
||||
<content-modal :contentID="roomInfoContentID" :ort_kurzbz="" dialogClass="modal-lg" ref="contentModal"/>
|
||||
<fhc-calendar @change:range="updateRange" :initial-date="currentDay" class="border-0" class-header="p-0" @select:day="selectDay" v-model:minimized="minimized" :events="events" no-week-view :show-weeks="false" />
|
||||
<div v-show="minimized" class="flex-grow-1 overflow-scroll">
|
||||
<div v-if="events === null" class="d-flex h-100 justify-content-center align-items-center">
|
||||
<i class="fa-solid fa-spinner fa-pulse fa-3x"></i>
|
||||
</div>
|
||||
<div v-else-if="currentEvents.length" class="list-group list-group-flush">
|
||||
<div role="button" @click="showLvUebersicht(evt)" class="" v-for="evt in currentEvents" :key="evt.id" class="list-group-item small" :style="{'background-color':evt.color}">
|
||||
<b>{{evt.topic}}</b>
|
||||
<br>
|
||||
<small class="d-flex w-100 justify-content-between">
|
||||
<!-- event modifier stop to prevent opening the modal for the lv Uebersicht when clicking on the ort_kurzbz -->
|
||||
<span @click.stop="showRoomInfoModal(evt.ort_kurzbz)" style="text-decoration:underline" type="button">{{evt.ort_kurzbz}}</span>
|
||||
<span>{{evt.start.toLocaleTimeString(undefined, {hour:'numeric',minute:'numeric'})}}-{{evt.end.toLocaleTimeString(undefined, {hour:'numeric',minute:'numeric'})}}</span>
|
||||
</small>
|
||||
<fhc-calendar @change:range="updateRange" :initial-date="currentDay" class="border-0" class-header="p-0" @select:day="selectDay" v-model:minimized="minimized" :events="events" no-week-view :show-weeks="false" >
|
||||
<template #minimizedPage >
|
||||
<div class="flex-grow-1 overflow-scroll">
|
||||
<div v-if="events === null" class="d-flex h-100 justify-content-center align-items-center">
|
||||
<i class="fa-solid fa-spinner fa-pulse fa-3x"></i>
|
||||
</div>
|
||||
<div v-else-if="currentEvents.length" class="list-group list-group-flush">
|
||||
<div role="button" @click="showLvUebersicht(evt)" class="" v-for="evt in currentEvents" :key="evt.id" class="list-group-item small" :style="{'background-color':evt.color}">
|
||||
<b>{{evt.topic}}</b>
|
||||
<br>
|
||||
<small class="d-flex w-100 justify-content-between">
|
||||
<!-- event modifier stop to prevent opening the modal for the lv Uebersicht when clicking on the ort_kurzbz -->
|
||||
<span @click.stop="showRoomInfoModal(evt.ort_kurzbz)" style="text-decoration:underline" type="button">{{evt.ort_kurzbz}}</span>
|
||||
<span>{{evt.start.toLocaleTimeString(undefined, {hour:'numeric',minute:'numeric'})}}-{{evt.end.toLocaleTimeString(undefined, {hour:'numeric',minute:'numeric'})}}</span>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="d-flex h-100 justify-content-center align-items-center fst-italic text-center">
|
||||
{{ p.t('lehre/noLvFound') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="d-flex h-100 justify-content-center align-items-center fst-italic text-center">
|
||||
{{ p.t('lehre/noLvFound') }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</fhc-calendar>
|
||||
|
||||
</div>`
|
||||
}
|
||||
Reference in New Issue
Block a user