fix loadEvents race condition; normalize route pushes; WIP getting route.replace to work;

This commit is contained in:
Johann Hoffmann
2025-02-24 17:53:56 +01:00
parent 7a0a2d756d
commit 881b7fb789
9 changed files with 60 additions and 56 deletions
@@ -556,16 +556,6 @@ class Lehrveranstaltung_model extends DB_Model
*/
public function getLvsByStudentWithGrades($student_uid, $studiensemester_kurzbz, $sprache = null, $lvid=null)
{
if ($sprache) {
$sprache_qry = $this->db->compile_binds('SELECT index FROM public.tbl_sprache WHERE sprache = ?', [$sprache]);
$bezeichnung = 'bezeichnung_mehrsprachig[(' . $sprache_qry . ')]';
$sgbezeichnung = $sprache == 'English' ? 'COALESCE(sg.english, sg.bezeichnung)' : 'sg.bezeichnung';
$lvbezeichnung = $sprache == 'English' ? 'COALESCE(v.bezeichnung_english, v.bezeichnung)' : 'v.bezeichnung';
} else {
$bezeichnung = 'bezeichnung';
$sgbezeichnung = 'sg.bezeichnung';
$lvbezeichnung = 'v.bezeichnung';
}
$this->addDistinct();
// TODO(chris): selects
@@ -605,16 +595,20 @@ class Lehrveranstaltung_model extends DB_Model
$this->addSelect('znn.positiv');
#$this->addSelect('splv.module');
$this->addSelect($lvbezeichnung . ' AS bezeichnung');
$this->addSelect($sgbezeichnung . ' AS sg_bezeichnung');
$this->addSelect('v.bezeichnung AS bezeichnung');
$this->addSelect('v.bezeichnung_english AS bezeichnung_eng');
$this->addSelect('sg.bezeichnung AS sg_bezeichnung');
$this->addSelect('sg.english AS sg_bezeichnung_eng');
$this->addSelect('UPPER(sg.typ::VARCHAR(1) || sg.kurzbz) AS studiengang_kuerzel');
//also adds returns the index of the grade
//TODO: ist zeugnissnote immer gleich wie die lvgesamtnote
$this->addSelect('COALESCE(zn.note::numeric,gn.note::numeric) as note_index');
$this->addSelect('COALESCE(znn.positiv,gnn.positiv) as positiv');
$this->addSelect('COALESCE(gnn.' . $bezeichnung . ', gnn.bezeichnung, gn.note::text) AS lvnote');
$this->addSelect('COALESCE(znn.' . $bezeichnung . ', znn.bezeichnung, zn.note::text) AS znote');
$this->addSelect('gnn.bezeichnung_mehrsprachig AS lvnotebez');
$this->addSelect('gnn.note AS lvnote');
$this->addSelect('znn.bezeichnung_mehrsprachig AS znotebez');
$this->addSelect('znn.note AS znote');
// TODO(chris): Potentielle Anpassung "Eine UID"
$this->addJoin('campus.vw_student_lehrveranstaltung v', 'lehrveranstaltung_id');
+3 -3
View File
@@ -22,7 +22,7 @@ export default {
this.focusDate.d += dir;
this.emitRangeChanged(previousDate);
},
emitRangeChanged(previousDate) {
emitRangeChanged(previousDate, mounted) {
this.$emit('change:range', { start: previousDate, end:this.focusDate });
},
prev() {
@@ -37,8 +37,8 @@ export default {
this.$emit('input', ['select:event', event]);
}
},
created() {
this.emitRangeChanged();
mounted() {
this.emitRangeChanged(new CalendarDate(this.focusDate.y, this.focusDate.m, this.focusDate.d -1), true);
},
template: /*html*/`
<div class="fhc-calendar-day">
+9 -7
View File
@@ -28,9 +28,14 @@ export default {
} else {
this.focusDate.moveMonthInDirection(dir)
}
this.emitRangeChanged()
},
emitRangeChanged(mounted = false) {
this.$emit('change:range', {
start: new Date(this.focusDate.y, this.focusDate.m, 1),
end: new Date(this.focusDate.y, this.focusDate.m+1, 0)
start: new Date(this.focusDate.y, this.focusDate.m, 1),
end: new Date(this.focusDate.y, this.focusDate.m+1, 0),
mounted
});
},
prev() {
@@ -55,11 +60,8 @@ export default {
this.$emit('input', ['select:day',day])
}
},
created() {
this.$emit('change:range', {
start: new Date(this.focusDate.y, this.focusDate.m, 1),
end: new Date(this.focusDate.y, this.focusDate.m+1, 0)
});
mounted() {
this.emitRangeChanged(true)
},
template: `
<div class="fhc-calendar-month">
+6 -1
View File
@@ -63,6 +63,10 @@ export default {
},
methods: {
handleEventClick(e, day) {
this.selectDay(day)
e.stopPropagation()
},
getDayClass(week, day) {
let classstring = 'fhc-calendar-month-page-day text-decoration-none overflow-hidden'
const isHighlightedWeek = this.isHighlightedWeek(week)
@@ -153,7 +157,8 @@ export default {
<span @click="clickEvent(day,week)" class="no" :style="getNumberStyle(day)">{{day.getDate()}}</span>
<span v-if="events[day.toDateString()] && events[day.toDateString()].length" class="events">
<div v-for="event in events[day.toDateString()]" :key="event.id"
:style="{'background-color': event.color}" class="fhc-entry" :selected="event == selectedEvent" v-contrast >
:style="{'background-color': event.color}" class="fhc-entry" :selected="event == selectedEvent"
v-contrast @click="handleEventClick($event, day)">
<slot name="monthPage" :event="event" :day="day" >
<p>this is a placeholder which means that no template was passed to the Calendar Page slot</p>
</slot>
+4 -4
View File
@@ -20,10 +20,10 @@ export default {
this.focusDate.d += dir * 7;
this.emitRangeChanged();
},
emitRangeChanged() {
emitRangeChanged(mounted = false) {
let start = this.focusDate.firstDayOfWeek;
let end = this.focusDate.lastDayOfWeek;
this.$emit('change:range', { start, end });
this.$emit('change:range', { start, end, mounted });
},
prev() {
this.$refs.pane.prev();
@@ -37,8 +37,8 @@ export default {
this.$emit('input', ['select:event',event]);
}
},
created() {
this.emitRangeChanged();
mounted() {
this.emitRangeChanged(true);
},
template: /*html*/`
<div class="fhc-calendar-week">
+2 -1
View File
@@ -22,7 +22,8 @@ export default {
lv.studiengang_kz + '#' + lv.semester,
{
studiengang_kz: lv.studiengang_kz,
bezeichnung: lv.sg_bezeichnung,
bezeichnung: lv.sg_bezeichnung,
sg_bezeichnung_eng: lv.sg_bezeichnung_eng,
kuerzel: lv.studiengang_kuerzel,
semester: lv.semester
}
@@ -12,7 +12,8 @@ export default {
bezeichnung: String,
kuerzel: String,
semester: [String,Number],
lvs: Array
lvs: Array,
sg_bezeichnung_eng: String
},
computed: {
lehrveranstaltungen() {
@@ -32,7 +33,7 @@ export default {
},
template: `<div class="card mb-3">
<div class="card-body">
<h4 class="card-title mb-3">{{bezeichnung}} - {{kuerzel}}
<h4 class="card-title mb-3">{{$p.user_language.value === 'English' ? sg_bezeichnung_eng : bezeichnung}} - {{kuerzel}}
<small>{{semester}}.{{$p.t('lehre/semester')}}</small>
</h4>
<div class="row">
@@ -29,7 +29,7 @@ export default {
ects: String,
incoming: Number,
positiv: Boolean,
note_index: String,
note_index: String
},
data: () => {
return {
@@ -66,8 +66,8 @@ export default {
return bodyStyle;
},
grade() {
// TODO: noten phrasen
return this.benotung ? this.znote || this.lvnote || null : null;
const languageIndex = this.$p.user_language.value === 'English' ? 1 : 0
return this.benotung ? this.znotebez[languageIndex] || this.lvnotebez[languageIndex] || null : null;
},
LvHasPruefungenInformation(){
return this.pruefungenData && this.pruefungenData.length > 0;
@@ -123,6 +123,7 @@ export default {
LvInfo.popup({
lehrveranstaltung_id: this.lehrveranstaltung_id,
bezeichnung: this.bezeichnung,
bezeichnung_eng: this.bezeichnung_eng,
studiengang_kuerzel: this.studiengang_kuerzel,
semester: this.semester,
studien_semester: this.studien_semester,
@@ -161,7 +162,7 @@ export default {
<div class="p-2" :class="is_organisatorische_einheit?'':'card-header'">
<!-- {{module}} if the module of the lv is important then query the module from the api endpoint for LV-->
<h6 class="fw-bold" v-if="is_organisatorische_einheit" >{{ $p.t('lehre/organisationseinheit') }}:</h6>
<h6 class="mb-0">{{bezeichnung}}</h6>
<h6 class="mb-0">{{$p.user_language.value === 'English' ? bezeichnung_eng : bezeichnung}}</h6>
</div>
<div v-if="!emptyMenu" class="card-body " :style="bodyStyle">
<template v-if="menu">
@@ -118,16 +118,17 @@ const Stundenplan = {
const date = day.getFullYear() + "-" +
String(day.getMonth() + 1).padStart(2, "0") + "-" +
String(day.getDate()).padStart(2, "0");
this.$router.push({
name: "Stundenplan",
params: {
mode: this.calendarMode,
focus_date: date,
lv_id: this.propsViewData?.lv_id || null
}
})
const capitalizedMode = this.calendarMode[0].toUpperCase() + this.calendarMode.slice(1);
this.$router.push({
name: "Stundenplan",
params: {
mode: capitalizedMode,
focus_date: date,
lv_id: this.propsViewData?.lv_id || null
}
})
this.currentDay = day;
},
handleOffset: function(offset) {
@@ -144,14 +145,14 @@ const Stundenplan = {
this.$router.push({
name: "Stundenplan",
params: {
mode: this.calendarMode,
mode: this.calendarMode[0].toUpperCase() + this.calendarMode.slice(1),
focus_date: date,
lv_id: this.propsViewData?.lv_id || null
}
})
},
handleChangeMode(mode) {
const modeCapitalized = mode.charAt(0).toUpperCase() + mode.slice(1)
let m = mode[0].toUpperCase() + mode.slice(1)
const date = this.currentDay.getFullYear() + "-" +
String(this.currentDay.getMonth() + 1).padStart(2, "0") + "-" +
String(this.currentDay.getDate()).padStart(2, "0");
@@ -159,30 +160,29 @@ const Stundenplan = {
this.$router.push({
name: "Stundenplan",
params: {
mode: modeCapitalized,
mode: m,
focus_date: date,
lv_id: this.propsViewData?.lv_id ?? null
}
})
this.calendarMode = mode
this.calendarMode = m
},
showModal: function(e, event){
e.stopPropagation()
this.currentlySelectedEvent = event;
Vue.nextTick(() => {
this.$refs.lvmodal.show();
});
},
updateRange: function ({start,end}) {
updateRange: function ({start,end, mounted}) {
let checkDate = (date) => {
return date.m != this.eventCalendarDate.m || date.y != this.eventCalendarDate.y;
}
this.calendarDate = new CalendarDate(end);
// only load month data if the month or year has changed
if (checkDate(new CalendarDate(start)) && checkDate(new CalendarDate(end))){
// or we receive a reload flag from the mounted routine of the components
// or this handler is being called from the mounted lifecycle of a component
if (mounted || (checkDate(new CalendarDate(start)) && checkDate(new CalendarDate(end)))){
// reset the events before querying the new events to activate the loading spinner
this.events = null;
this.eventCalendarDate = new CalendarDate(end);
@@ -238,7 +238,7 @@ const Stundenplan = {
.then(data=>{
this.uid = data.uid;
})
this.loadEvents();
},
beforeUnmount() {
if(this.$refs.lvmodal) this.$refs.lvmodal.hide()
@@ -275,7 +275,7 @@ const Stundenplan = {
</div>
</template>
<template #monthPage="{event,day}">
<div @click="showModal($event, event); ">
<div>
<span class="fhc-entry">
{{event.topic}}
</span>