diff --git a/application/config/routes.php b/application/config/routes.php index ede5cc9bd..eb4c267ce 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -61,17 +61,7 @@ $route['api/v1/organisation/[O|o]rganisationseinheit/(:any)'] = 'api/v1/organisa $route['api/v1/ressource/[B|b]etriebsmittelperson/(:any)'] = 'api/v1/ressource/betriebsmittelperson2/$1'; $route['api/v1/system/[S|s]prache/(:any)'] = 'api/v1/system/sprache2/$1'; -$route['Cis/Stundenplan'] = 'Cis/Stundenplan/index/null/null/null'; -$route['Cis/Stundenplan/(:num)'] = 'Cis/Stundenplan/index/null/null/$1'; -$route['Cis/Stundenplan/(:num)/(:any)'] = 'Cis/Stundenplan/index/null/$2/$1'; - -// Specific route (for mode: month|week|day, focusdate, lv_id optional) -$route['Cis/Stundenplan/([M|m]onth|[W|w]eek|[D|d]ay)'] = 'Cis/Stundenplan/index/$1'; -$route['Cis/Stundenplan/([M|m]onth|[W|w]eek|[D|d]ay)(/(:any))?'] = 'Cis/Stundenplan/index/$1/$3'; -$route['Cis/Stundenplan/([M|m]onth|[W|w]eek|[D|d]ay)(/(:any))?(/(:num))?'] = 'Cis/Stundenplan/index/$1/$3/$5'; - - - +$route['Cis/Stundenplan/.*'] = 'Cis/Stundenplan/index/$1'; // load routes from extensions $subdir = 'application/config/extensions'; diff --git a/application/controllers/Cis/Stundenplan.php b/application/controllers/Cis/Stundenplan.php index 5b7c25b21..71e01be8b 100644 --- a/application/controllers/Cis/Stundenplan.php +++ b/application/controllers/Cis/Stundenplan.php @@ -23,19 +23,10 @@ class Stundenplan extends Auth_Controller /** * @return void */ - public function index($mode = 'Week', $focus_date = null, $lv_id = null) + public function index() { - // convert string "null" to actual null values -> ci3 reroute fix - $mode = ($mode === 'null') ? 'Week' : ucfirst(strtolower($mode)); - $focus_date = ($focus_date === 'null') ? date('Y-m-d') : $focus_date; - $lv_id = ($lv_id === 'null') ? null : $lv_id; - - if($mode) $mode = ucfirst(strtolower($mode)); $viewData = array( - 'mode' => $mode, - 'focus_date' => $focus_date, - 'lv_id' => $lv_id, 'uid'=>getAuthUID(), ); diff --git a/application/controllers/api/frontend/v1/Stundenplan.php b/application/controllers/api/frontend/v1/Stundenplan.php index 0a56dac71..2ec02fea9 100644 --- a/application/controllers/api/frontend/v1/Stundenplan.php +++ b/application/controllers/api/frontend/v1/Stundenplan.php @@ -153,6 +153,11 @@ class Stundenplan extends FHCAPI_Controller $stundenplan_data = $this->StundenplanModel->getStundenplanLVA($start_date, $end_date, $lv_id); $stundenplan_data = $this->getDataOrTerminateWithError($stundenplan_data) ?? []; $this->expand_object_information($stundenplan_data); + + // query lv itself in case its Stundenplan is being queried and it has no entries + $this->load->model('education/Lehrveranstaltung_model','LehrveranstaltungModel'); + $lv = getData($this->LehrveranstaltungModel->load($lv_id))[0]; + $this->addMeta('lv', $lv); $this->terminateWithSuccess($stundenplan_data); } diff --git a/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js index a4cbb421d..e3ba786f1 100644 --- a/public/js/apps/Dashboard/Fhc.js +++ b/public/js/apps/Dashboard/Fhc.js @@ -37,8 +37,10 @@ const router = VueRouter.createRouter({ redirect: (to) => { return { // redirect to longer Rauminfo url and map params name: "RoomInformation", - params: { - ort_kurzbz: to.params.ort_kurzbz + params: { // in this case always populate other params since they are not optional + ort_kurzbz: to.params.ort_kurzbz, + mode: DEFAULT_MODE_RAUMINFO, + focus_date: new Date().toISOString().split("T")[0] }, }; }, @@ -57,7 +59,8 @@ const router = VueRouter.createRouter({ : DEFAULT_MODE_RAUMINFO; // default to today date if not provided - const focus_date = route.params.focus_date || new Date().toISOString().split("T")[0]; + const d = new Date(route.params.focus_date) + const focus_date = !isNaN(d) ? route.params.focus_date : new Date().toISOString().split("T")[0]; // for consistency reasons format the props into one object but actually use a new name to we dont collide with // existing viewData declaration written from codeigniter 3 into routerview tag @@ -137,8 +140,9 @@ const router = VueRouter.createRouter({ ? route.params.mode.charAt(0).toUpperCase() + route.params.mode.slice(1).toLowerCase() : DEFAULT_MODE_STUNDENPLAN; - // default to today date if not provided - const focus_date = route.params.focus_date || new Date().toISOString().split("T")[0]; + // default to today date if not provided or string forms invalid date + const d = new Date(route.params.focus_date) + const focus_date = !isNaN(d) ? route.params.focus_date : new Date().toISOString().split("T")[0]; // for consistency reasons format the props into one object but actually use a new name to we dont collide with // existing viewData declaration written from codeigniter 3 into routerview tag return { @@ -227,7 +231,7 @@ const app = Vue.createApp({ // let click event propagate normally if we dont route internally const res = this.$router.resolve(route) - if(!res?.matched?.length) return + if(!res?.matched?.length || res.name === 'Fallback') return event.preventDefault(); // Prevent browser navigation diff --git a/public/js/components/Calendar/Calendar.js b/public/js/components/Calendar/Calendar.js index 8eed731cd..cd935b2ad 100644 --- a/public/js/components/Calendar/Calendar.js +++ b/public/js/components/Calendar/Calendar.js @@ -95,7 +95,8 @@ export default { 'select:event', 'change:range', 'update:minimized', - 'selectedEvent' + 'selectedEvent', + 'change:offset' ], data() { return { @@ -240,7 +241,8 @@ export default { }, template: /*html*/`
- + diff --git a/public/js/components/Calendar/Day.js b/public/js/components/Calendar/Day.js index 2f07efef3..c0f1040f5 100644 --- a/public/js/components/Calendar/Day.js +++ b/public/js/components/Calendar/Day.js @@ -27,9 +27,11 @@ export default { }, prev() { this.$refs.pane.prev(); + this.$emit('change:offset', { y: 0, m: 0, d: -1 }); }, next() { this.$refs.pane.next(); + this.$emit('change:offset', { y: 0, m: 0, d: 1 }); }, selectEvent(event) { this.$emit('input', ['select:event', event]); diff --git a/public/js/components/Calendar/Day/Page.js b/public/js/components/Calendar/Day/Page.js index 70bccc49d..a57fb97af 100644 --- a/public/js/components/Calendar/Day/Page.js +++ b/public/js/components/Calendar/Day/Page.js @@ -36,6 +36,7 @@ export default { 'calendarClientHeight', 'setSelectedEvent', 'selectedEvent', + 'rowMinHeight' ], props: { year: Number, @@ -372,11 +373,12 @@ export default {
-
{{hour}}:00
+
{{hour}}:00
-
+
diff --git a/public/js/components/Calendar/Month.js b/public/js/components/Calendar/Month.js index 79fc1bf23..513ed1c8c 100644 --- a/public/js/components/Calendar/Month.js +++ b/public/js/components/Calendar/Month.js @@ -35,9 +35,11 @@ export default { }, prev() { this.$refs.pane.prev(); + this.$emit('change:offset', { y: 0, m: -1, d: 0 }); }, next() { this.$refs.pane.next(); + this.$emit('change:offset', { y: 0, m: 1, d: 0 }); }, selectDay(day) { let m = day.getMonth(); diff --git a/public/js/components/Calendar/Month/Page.js b/public/js/components/Calendar/Month/Page.js index 04e3a8e64..8ec700ce7 100644 --- a/public/js/components/Calendar/Month/Page.js +++ b/public/js/components/Calendar/Month/Page.js @@ -143,16 +143,16 @@ export default { {{week.no}} - {{day.getDate()}} + {{day.getDate()}} -

this is a placeholder which means that no template was passed to the Calendar Page slot

diff --git a/public/js/components/Calendar/Week.js b/public/js/components/Calendar/Week.js index 9a42f9659..350f0130d 100644 --- a/public/js/components/Calendar/Week.js +++ b/public/js/components/Calendar/Week.js @@ -27,9 +27,11 @@ export default { }, prev() { this.$refs.pane.prev(); + this.$emit('change:offset', { y: 0, m: 0, d: -7 }); }, next() { this.$refs.pane.next(); + this.$emit('change:offset', { y: 0, m: 0, d: 7 }); }, selectEvent(event) { this.$emit('input', ['select:event',event]); diff --git a/public/js/components/Calendar/Week/Page.js b/public/js/components/Calendar/Week/Page.js index d6e5c6df0..c9f751f66 100644 --- a/public/js/components/Calendar/Week/Page.js +++ b/public/js/components/Calendar/Week/Page.js @@ -23,7 +23,8 @@ export default { 'noMonthView', 'isSliding', 'selectedEvent', - 'setSelectedEvent' + 'setSelectedEvent', + 'rowMinHeight' ], props: { year: Number, @@ -38,7 +39,7 @@ export default { computed: { getGridStyle() { return { - 'min-height': '100px', + 'min-height': this.rowMinHeight, // this.size is the magic number anyway which directs font-size, // which in turn influences a lot of layout width: '42px' @@ -272,6 +273,11 @@ export default { this.$emit('updateMode', 'month'); } }, + changeToDay(day) { + this.date.set(day); + this.focusDate.set(day); + this.$emit('updateMode', 'day'); + }, dateToMinutesOfDay(day) { // subtract 7 from the total hours because the hours range from 7 to 24 return Math.floor(((day.getHours()-7) * 60 + day.getMinutes()) / this.smallestTimeFrame) + 1; @@ -320,7 +326,7 @@ export default {
-
+ diff --git a/public/js/components/Calendar/Weeks.js b/public/js/components/Calendar/Weeks.js index 844101b88..76243c67b 100644 --- a/public/js/components/Calendar/Weeks.js +++ b/public/js/components/Calendar/Weeks.js @@ -32,7 +32,7 @@ export default { }, }, template: ` -
+
diff --git a/public/js/components/Calendar/Years.js b/public/js/components/Calendar/Years.js index 6cda6cfe9..baff2eb6c 100644 --- a/public/js/components/Calendar/Years.js +++ b/public/js/components/Calendar/Years.js @@ -41,9 +41,11 @@ export default { }, prev() { this.$refs.pane.prev(); + this.$emit('change:offset', { y: -1, m: 0, d: 0 }); }, next() { this.$refs.pane.next(); + this.$emit('change:offset', { y: 1, m: 0, d: 0 }); } }, created() { diff --git a/public/js/components/Calendar/Years/Page.js b/public/js/components/Calendar/Years/Page.js index c6efe0ffc..3d78fc38d 100644 --- a/public/js/components/Calendar/Years/Page.js +++ b/public/js/components/Calendar/Years/Page.js @@ -18,6 +18,13 @@ export default { return [...Array(this.end - this.start).keys()].map(i => i + this.start); } }, + mounted() { + const container = document.getElementById("calendarContainer") + if(container) { + container.style['overflow-y'] = 'scroll' + container.style['overflow-x'] = 'auto' + } + }, template: `
diff --git a/public/js/components/Cis/Mylv/RoomInformation.js b/public/js/components/Cis/Mylv/RoomInformation.js index c89756faa..8a7354305 100644 --- a/public/js/components/Cis/Mylv/RoomInformation.js +++ b/public/js/components/Cis/Mylv/RoomInformation.js @@ -10,6 +10,14 @@ const RoomInformation = { props:{ propsViewData: { type: Object + }, + rowMinHeight: { + type: String, + default: '100px' + }, + eventMaxHeight: { + type: String, + default: '125px' } }, components: { @@ -17,6 +25,12 @@ const RoomInformation = { LvModal, LvInfo, }, + provide() { + return { + rowMinHeight: this.rowMinHeight, + eventMaxHeight: this.eventMaxHeight + } + }, data() { return { events: null, @@ -79,14 +93,37 @@ const RoomInformation = { this.currentDay = day; }, + handleOffset: function(offset) { + this.currentDay = new Date( + this.currentDay.getFullYear() + offset.y, + this.currentDay.getMonth() + offset.m, + this.currentDay.getDate() + offset.d + ) + + const date = this.currentDay.getFullYear() + "-" + + String(this.currentDay.getMonth() + 1).padStart(2, "0") + "-" + + String(this.currentDay.getDate()).padStart(2, "0"); + + this.$router.push({ + name: "Stundenplan", + params: { + mode: this.calendarMode, + focus_date: date, + lv_id: this.propsViewData?.lv_id || null + } + }) + }, handleChangeMode(mode) { const modeCapitalized = mode.charAt(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"); + this.$router.push({ name: "RoomInformation", params: { mode: modeCapitalized, - focus_date: this.currentDay.toISOString().split("T")[0], + focus_date: date, ort_kurzbz: this.propsViewData.ort_kurzbz } }) @@ -167,7 +204,8 @@ const RoomInformation = { ref="calendar" @selectedEvent="setSelectedEvent" :initial-date="currentDay" - @change:range="updateRange" + @change:range="updateRange" + @change:offset="handleOffset" :events="events" :initial-mode="propsViewData.mode" show-weeks diff --git a/public/js/components/Cis/Stundenplan/Stundenplan.js b/public/js/components/Cis/Stundenplan/Stundenplan.js index 43d7e3250..3fee43058 100644 --- a/public/js/components/Cis/Stundenplan/Stundenplan.js +++ b/public/js/components/Cis/Stundenplan/Stundenplan.js @@ -16,6 +16,7 @@ const Stundenplan = { eventCalendarDate: new CalendarDate(new Date()), currentlySelectedEvent: null, currentDay: this.propsViewData?.focus_date ? new Date(this.propsViewData.focus_date) : new Date(), + lv: null, minimized: false, studiensemester_kurzbz: null, studiensemester_start: null, @@ -24,7 +25,21 @@ const Stundenplan = { } }, props: { - propsViewData: Object + propsViewData: Object, + rowMinHeight: { + type: String, + default: '100px' + }, + eventMaxHeight: { + type: String, + default: '125px' + } + }, + provide() { + return { + rowMinHeight: this.rowMinHeight, + eventMaxHeight: this.eventMaxHeight + } }, watch: { weekFirstDay: { @@ -59,8 +74,17 @@ const Stundenplan = { let ende = new Date(this.studiensemester_ende); ende = Math.floor(ende.getTime() / 1000); - let download_link = (format, version = "", target = "") => `${FHC_JS_DATA_STORAGE_OBJECT.app_root}cis/private/lvplan/stpl_kalender.php?type=student&pers_uid=${this.uid}&begin=${start}&ende=${ende}&format=${format}${version ? '&version=' + version : ''}${target ? '&target=' + target : ''}`; - return [{ title: "excel", icon: 'fa-solid fa-file-excel', link: download_link('excel') }, { title: "csv", icon: 'fa-solid fa-file-csv', link: download_link('csv') }, { title: "ical1", icon: 'fa-regular fa-calendar', link: download_link('ical', '1', 'ical') }, { title: "ical2", icon: 'fa-regular fa-calendar', link: download_link('ical', '2', 'ical') }]; + let download_link = + (format, version = "", target = "") => + `${FHC_JS_DATA_STORAGE_OBJECT.app_root}cis/private/lvplan/stpl_kalender.php?type=student&pers_uid= + ${this.uid}&begin=${start}&ende=${ende}&format=${format} + ${version ? '&version=' + version : ''}${target ? '&target=' + target : ''}`; + return [ + { title: "excel", icon: 'fa-solid fa-file-excel', link: download_link('excel') }, + { title: "csv", icon: 'fa-solid fa-file-csv', link: download_link('csv') }, + { title: "ical1", icon: 'fa-regular fa-calendar', link: download_link('ical', '1', 'ical') }, + { title: "ical2", icon: 'fa-regular fa-calendar', link: download_link('ical', '2', 'ical') } + ]; }, weekFirstDay: function () { return this.calendarDateToString(this.calendarDate.cdFirstDayOfWeek); @@ -94,7 +118,7 @@ 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: { @@ -106,28 +130,52 @@ const Stundenplan = { this.currentDay = day; }, + handleOffset: function(offset) { + this.currentDay = new Date( + this.currentDay.getFullYear() + offset.y, + this.currentDay.getMonth() + offset.m, + this.currentDay.getDate() + offset.d + ) + + const date = this.currentDay.getFullYear() + "-" + + String(this.currentDay.getMonth() + 1).padStart(2, "0") + "-" + + String(this.currentDay.getDate()).padStart(2, "0"); + + this.$router.push({ + name: "Stundenplan", + params: { + mode: this.calendarMode, + focus_date: date, + lv_id: this.propsViewData?.lv_id || null + } + }) + }, handleChangeMode(mode) { const modeCapitalized = mode.charAt(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"); this.$router.push({ name: "Stundenplan", params: { mode: modeCapitalized, - focus_date: this.currentDay.toISOString().split("T")[0], + focus_date: date, lv_id: this.propsViewData?.lv_id ?? null } }) this.calendarMode = mode }, - showModal: function(event){ + showModal: function(e, event){ + e.stopPropagation() this.currentlySelectedEvent = event; Vue.nextTick(() => { this.$refs.lvmodal.show(); }); }, updateRange: function ({start,end}) { - + let checkDate = (date) => { return date.m != this.eventCalendarDate.m || date.y != this.eventCalendarDate.y; } @@ -157,7 +205,9 @@ const Stundenplan = { let promise_events = []; result.forEach((promise_result) => { if (promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success") { - + + if(promise_result.value.meta?.lv) this.lv = promise_result.value.meta.lv + let data = promise_result.value.data; // adding additional information to the events if (data && data.forEach) { @@ -194,7 +244,11 @@ const Stundenplan = { if(this.$refs.lvmodal) this.$refs.lvmodal.hide() }, template:/*html*/` -

{{$p.t('lehre/stundenplan')}}

+

+ {{$p.t('lehre/stundenplan')}} + {{studiensemester_kurzbz}} + {{ $p.user_language.value === 'German' ? lv?.bezeichnung : lv?.bezeichnung_english}} +