From 2eb58e334669f1b150ae1edbe3639150873c5aed Mon Sep 17 00:00:00 2001 From: adisposkofh Date: Thu, 23 Apr 2026 11:43:25 +0200 Subject: [PATCH] reworked how 'compactible event types' are defined --- .../controllers/api/frontend/v1/LvPlan.php | 11 ++ public/js/api/factory/lvPlan.js | 8 +- .../js/components/Calendar/Base/Grid/Line.js | 12 +- public/js/components/Calendar/LvPlan.js | 135 ++++++++++-------- 4 files changed, 99 insertions(+), 67 deletions(-) diff --git a/application/controllers/api/frontend/v1/LvPlan.php b/application/controllers/api/frontend/v1/LvPlan.php index 99dc8bf59..dc87732b9 100644 --- a/application/controllers/api/frontend/v1/LvPlan.php +++ b/application/controllers/api/frontend/v1/LvPlan.php @@ -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 * diff --git a/public/js/api/factory/lvPlan.js b/public/js/api/factory/lvPlan.js index 41aa29299..0b652025f 100644 --- a/public/js/api/factory/lvPlan.js +++ b/public/js/api/factory/lvPlan.js @@ -123,5 +123,11 @@ export default { method: 'get', url: '/api/frontend/v1/lvPlan/permissionOtherLvPlan', } - } + }, + getCompactibleEventTypes(){ + return { + method: 'get', + url: '/api/frontend/v1/lvPlan/compactibleEventTypes', + } + }, }; \ No newline at end of file diff --git a/public/js/components/Calendar/Base/Grid/Line.js b/public/js/components/Calendar/Base/Grid/Line.js index e5241de1d..6519e63d9 100644 --- a/public/js/components/Calendar/Base/Grid/Line.js +++ b/public/js/components/Calendar/Base/Grid/Line.js @@ -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 = []; diff --git a/public/js/components/Calendar/LvPlan.js b/public/js/components/Calendar/LvPlan.js index 7f96b3d2f..e448741fa 100644 --- a/public/js/components/Calendar/LvPlan.js +++ b/public/js/components/Calendar/LvPlan.js @@ -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 */ ` - ` -} + `, +};