reworked how 'compactible event types' are defined

This commit is contained in:
adisposkofh
2026-04-23 11:43:25 +02:00
parent e57846566e
commit 2eb58e3346
4 changed files with 99 additions and 67 deletions
@@ -48,6 +48,7 @@ class LvPlan extends FHCAPI_Controller
'getStudiengaenge' => self::PERM_LOGGED,
'getLehrverband' => self::PERM_LOGGED,
'permissionOtherLvPlan' => self::PERM_LOGGED,
'compactibleEventTypes' => self::PERM_LOGGED,
]);
$this->load->library('LogLib');
@@ -393,6 +394,16 @@ class LvPlan extends FHCAPI_Controller
$this->terminateWithSuccess($this->permissionlib->isBerechtigt('basis/other_lv_plan'));
}
/**
* get event types which can be compacted in lv plan display
*
* @return void
*/
public function compactibleEventTypes()
{
$this->terminateWithSuccess(["lehreinheit", "reservierung"]);
}
/**
* fetch moodle events
*
+7 -1
View File
@@ -123,5 +123,11 @@ export default {
method: 'get',
url: '/api/frontend/v1/lvPlan/permissionOtherLvPlan',
}
}
},
getCompactibleEventTypes(){
return {
method: 'get',
url: '/api/frontend/v1/lvPlan/compactibleEventTypes',
}
},
};
@@ -12,7 +12,7 @@ export default {
LineEvent,
LineBackground,
},
inject: ["axisRow", "shouldCompactEvents"],
inject: ["axisRow", "shouldCompactEvents", "compactibleEventTypes"],
props: {
date: {
type: luxon.DateTime,
@@ -50,27 +50,27 @@ export default {
return event;
});
if (this.shouldCompactEvents) {
if (this.shouldCompactEvents && this.compactibleEventTypes?.length) {
formattedEvents =
this.compactEventsForMobileView(formattedEvents);
this.compactEventsForMobileView(formattedEvents, this.compactibleEventTypes);
}
return formattedEvents;
},
},
methods: {
compactEventsForMobileView(events) {
compactEventsForMobileView(events, compactibleEventTypes) {
let formattedEvents = events
.filter(
(event) =>
!["lehreinheit", "reservierung"].includes(event.type),
!compactibleEventTypes.includes(event.type),
)
.map((event) => {
event.display = "default";
return event;
});
let eventsToBeCompacted = events.filter((event) =>
["lehreinheit", "reservierung"].includes(event.type),
compactibleEventTypes.includes(event.type),
);
let compactedEvents = [];
+75 -60
View File
@@ -1,92 +1,98 @@
import FhcCalendar from "./Base.js";
import ApiLvPlan from '../../api/factory/lvPlan.js';
import ApiLvPlan from "../../api/factory/lvPlan.js";
import { useEventLoader } from '../../composables/EventLoader.js';
import { useEventLoader } from "../../composables/EventLoader.js";
import ModeDay from './Mode/Day.js';
import ModeWeek from './Mode/Week.js';
import ModeMonth from './Mode/Month.js';
import ModeList from './Mode/List.js';
import ModeDay from "./Mode/Day.js";
import ModeWeek from "./Mode/Week.js";
import ModeMonth from "./Mode/Month.js";
import ModeList from "./Mode/List.js";
export default {
name: "CalendarLvPlan",
components: {
FhcCalendar
FhcCalendar,
},
inject: [
"renderers",
"isMobile",
],
inject: ["renderers", "isMobile"],
props: {
timezone: {
type: String,
required: true
required: true,
},
date: {
type: [Date, String, Number, luxon.DateTime],
default: luxon.DateTime.local()
default: luxon.DateTime.local(),
},
mode: {
type: String,
default: 'Day'
default: "Day",
},
getPromiseFunc: {
type: Function,
required: true
}
required: true,
},
},
provide() {
return {
shouldCompactEvents: Vue.computed(() => this.$props.mode === "Month" && this.isMobile)
}
shouldCompactEvents: Vue.computed(
() => this.$props.mode === "Month" && this.isMobile,
),
compactibleEventTypes: Vue.computed(
() => this.compactibleEventTypes,
),
};
},
emits: [
"update:date",
"update:mode",
"update:range"
],
emits: ["update:date", "update:mode", "update:range"],
data() {
return {
modeOptions: {
day: {
emptyMessage: Vue.computed(() => this.$p.t('lehre/noLvFound')),
emptyMessageDetails: Vue.computed(() => this.$p.t('lehre/noLvFound'))
emptyMessage: Vue.computed(() =>
this.$p.t("lehre/noLvFound"),
),
emptyMessageDetails: Vue.computed(() =>
this.$p.t("lehre/noLvFound"),
),
},
week: {
collapseEmptyDays: false
collapseEmptyDays: false,
},
list: {
length: 7
}
length: 7,
},
},
teachingunits: null
teachingunits: null,
compactibleEventTypes: [],
};
},
computed: {
backgrounds() {
let now = luxon.DateTime.now().setZone(this.timezone);
if (this.mode == 'Month')
if (this.mode == "Month")
return [
{
class: 'background-past',
end: now.startOf('day')
}
class: "background-past",
end: now.startOf("day"),
},
];
return [
{
class: 'background-past',
class: "background-past",
end: now,
label: now.startOf('minute').toISOTime({ suppressSeconds: true, includeOffset: false })
}
label: now.startOf("minute").toISOTime({
suppressSeconds: true,
includeOffset: false,
}),
},
];
},
modes() {
let modes = {
day: Vue.markRaw(ModeDay),
month: Vue.markRaw(ModeMonth)
month: Vue.markRaw(ModeMonth),
};
if (this.isMobile) {
modes.list = Vue.markRaw(ModeList);
@@ -99,46 +105,55 @@ export default {
},
methods: {
eventStyle(event) {
if (!event.farbe)
return undefined;
return '--event-bg:#' + event.farbe;
if (!event.farbe) return undefined;
return "--event-bg:#" + event.farbe;
},
updateRange(rangeInterval) {
this.rangeInterval = rangeInterval;
this.$emit('update:range', rangeInterval);
this.$emit("update:range", rangeInterval);
},
resetEventLoader() {
this.reset();
}
},
async getStunden() {
let stundenResponse = await this.$api.call(ApiLvPlan.getStunden());
this.teachingunits = stundenResponse.data.map((el) => ({
id: el.stunde,
start: el.beginn,
end: el.ende,
}));
},
async getCompactibleEventTypes() {
let compactibleEventTypesResponse = await this.$api.call(
ApiLvPlan.getCompactibleEventTypes(),
);
this.compactibleEventTypes = compactibleEventTypesResponse.data;
},
},
setup(props, context) {
const rangeInterval = Vue.ref(null);
const { events, lv, reset } = useEventLoader(rangeInterval, props.getPromiseFunc);
Vue.watch(lv, newValue => {
context.emit('update:lv', newValue);
const { events, lv, reset } = useEventLoader(
rangeInterval,
props.getPromiseFunc,
);
Vue.watch(lv, (newValue) => {
context.emit("update:lv", newValue);
});
return {
rangeInterval,
events,
lv,
reset
reset,
};
},
created() {
this.$api
.call(ApiLvPlan.getStunden())
.then(res => {
return this.teachingunits = res.data.map(el => ({
id: el.stunde,
start: el.beginn,
end: el.ende
}));
});
async created() {
await this.getStunden();
await this.getCompactibleEventTypes();
},
template: /* html */`
template: /* html */ `
<fhc-calendar
ref="calendar"
class="fhc-calendar-lvplan"
@@ -189,5 +204,5 @@ export default {
<template #actions>
<slot />
</template>
</fhc-calendar>`
}
</fhc-calendar>`,
};