From d45a41b949fa5e8605630ed71063dc46fa4a1767 Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Tue, 18 Feb 2025 10:18:39 +0100 Subject: [PATCH 1/6] defined new CI routes to differentiate between 5 cases CI doesnt handle anymore but vue router does; define Stundenplan/:lv_id? route for old links to redirect to new route Stundenplan/:mode/:focus_date/lv_id; new route with props route param handling to put them into viewData to always check for the same object; define day as allowed init mode; WIP same thing for raum calendar page; --- application/config/routes.php | 12 +++- application/controllers/Cis/Stundenplan.php | 11 ++- public/js/apps/Dashboard/Fhc.js | 65 ++++++++++++++++- public/js/components/Calendar/Calendar.js | 6 +- public/js/components/Calendar/Week/Page.js | 1 + .../components/Cis/Stundenplan/Stundenplan.js | 70 +++++++++++++++---- 6 files changed, 143 insertions(+), 22 deletions(-) diff --git a/application/config/routes.php b/application/config/routes.php index 8acf9b5ea..ede5cc9bd 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -61,7 +61,17 @@ $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/(:any)?'] = 'Cis/Stundenplan/index/$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'; + + + // load routes from extensions $subdir = 'application/config/extensions'; diff --git a/application/controllers/Cis/Stundenplan.php b/application/controllers/Cis/Stundenplan.php index f6fb0bd67..c9c486a47 100644 --- a/application/controllers/Cis/Stundenplan.php +++ b/application/controllers/Cis/Stundenplan.php @@ -23,9 +23,18 @@ class Stundenplan extends Auth_Controller /** * @return void */ - public function index($lv_id = null) + public function index($mode = 'Week', $focus_date = null, $lv_id = null) { + // 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/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js index 9f77d4b9b..aba5d2f40 100644 --- a/public/js/apps/Dashboard/Fhc.js +++ b/public/js/apps/Dashboard/Fhc.js @@ -58,10 +58,71 @@ const router = VueRouter.createRouter({ component: Info, props: true }, + // Redirect old links to new format { - path: `/Cis/Stundenplan/:lv_id?`, + path: "/Cis/Stundenplan/:lv_id(\\d+)", // define lv_id as numeric so this matches + name: "StundenplanNumeric", + component: Stundenplan, + redirect: (to) => { + debugger + return { // redirect to longer Stundenplan url and map params + name: "Stundenplan", + params: { + mode: "Week", + focus_date: new Date().toISOString().split("T")[0], + lv_id: to.params.lv_id || null + + }, + }; + }, + }, + { + // actual routes after Stundenplan -> config/routes.php + // actual param handling -> controllers/Cis/Stundenplan.php + path: `/Cis/Stundenplan/:mode?/:focus_date?/:lv_id?`, name: 'Stundenplan', - component: Stundenplan + component: Stundenplan, + props: (route) => { // validate and set mode/focus date if for some reason missing + const validModes = ["Month", "Week", "Day"]; + + // default to mode week if not provided + let mode = route.params.mode && + validModes.includes(route.params.mode.charAt(0).toUpperCase() + route.params.mode.slice(1).toLowerCase()) + ? route.params.mode.charAt(0).toUpperCase() + route.params.mode.slice(1).toLowerCase() + : "Week"; + + // default focus_date: today date if not provided + let focusDate = route.params.focus_date || new Date().toISOString().split("T")[0]; + + // for consistency reasons format the props into the viewData object so we have consistency in the form + // we access route specific data whether it is codigniter served or just another vue component that has been + // mounted + return { + viewData: { + mode, + focusDate, + lv_id: route.params.lv_id || null + } + }; + }, + beforeEnter: (to, from, next) => { + console.log('beforeEnter') + // If missing mode or focus_date, redirect with defaults + if (!to.params.mode || !to.params.focus_date) { + next({ + name: "Stundenplan", + params: { + + mode: to.params.mode || "Week", + focus_date: to.params.focus_date || new Date().toISOString().split("T")[0], + lv_id: to.params.lv_id || null + + }, + }); + } else { + next(); + } + } }, { path: `/`, diff --git a/public/js/components/Calendar/Calendar.js b/public/js/components/Calendar/Calendar.js index 8d4c56cfe..f9d836bd1 100644 --- a/public/js/components/Calendar/Calendar.js +++ b/public/js/components/Calendar/Calendar.js @@ -192,12 +192,13 @@ export default { }, }, created() { - const allowedInitialModes = ['years']; + const initMode = this.initialMode.toLowerCase() + const allowedInitialModes = ['years', 'day']; if (!this.noWeekView) allowedInitialModes.push('week'); if (!this.noMonthView) allowedInitialModes.push('month'); - this.mode = allowedInitialModes[allowedInitialModes.indexOf(this.initialMode)] || allowedInitialModes.pop(); + this.mode = allowedInitialModes[allowedInitialModes.indexOf(initMode)] || allowedInitialModes.pop(); this.date.set(new Date(this.initialDate)); this.focusDate.set(this.date); }, @@ -227,7 +228,6 @@ export default { } }).observe(this.$refs.container); } - }, unmounted(){ CalendarDates.cleanup(); diff --git a/public/js/components/Calendar/Week/Page.js b/public/js/components/Calendar/Week/Page.js index 10ff6c495..d6e5c6df0 100644 --- a/public/js/components/Calendar/Week/Page.js +++ b/public/js/components/Calendar/Week/Page.js @@ -273,6 +273,7 @@ export default { } }, 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; }, weekPageClick(event, day) { diff --git a/public/js/components/Cis/Stundenplan/Stundenplan.js b/public/js/components/Cis/Stundenplan/Stundenplan.js index 8fc9b77d4..5a6ad9c09 100644 --- a/public/js/components/Cis/Stundenplan/Stundenplan.js +++ b/public/js/components/Cis/Stundenplan/Stundenplan.js @@ -4,24 +4,26 @@ import LvModal from "../Mylv/LvModal.js"; import LvInfo from "../Mylv/LvInfo.js" import LvMenu from "../Mylv/LvMenu.js" +// TODO: define in one place that week is the default mode, it is hardcoded in 27 places currently export const Stundenplan = { name: 'Stundenplan', data() { return { events: null, + calendarMode: "Week", calendarDate: new CalendarDate(new Date()), eventCalendarDate: new CalendarDate(new Date()), currentlySelectedEvent: null, - currentDay: new Date(), + currentDay: this.viewData?.focus_date ? new Date(this.viewData.focus_date) : new Date(), minimized: false, - studiensemester_kurzbz:null, - studiensemester_start:null, - studiensemester_ende:null, - uid:null, + studiensemester_kurzbz: null, + studiensemester_start: null, + studiensemester_ende: null, + uid: null, } }, props: [ - "viewData", + "viewData" ], watch: { weekFirstDay: { @@ -33,6 +35,12 @@ export const Stundenplan = { this.studiensemester_ende = ende; }, immediate: true, + }, + 'viewData.lv_id'(newVal) { + // console.log('viewData.lv_id', newVal) + }, + 'viewData.focus_date'(newVal) { + // console.log('viewData.focus_date', newVal) } }, components: { @@ -49,11 +57,6 @@ export const Stundenplan = { 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') }]; }, - lv_id() { // computed so we can theoretically change path/lva selection and reload without page refresh - const pathParts = window.location.pathname.split('/').filter(Boolean); - const id = pathParts[pathParts.length - 1]; - return id && !isNaN(Number(id)) ? id : null; // only return id if it is a number string since the path might contain invalid elements - }, weekFirstDay: function () { return this.calendarDateToString(this.calendarDate.cdFirstDayOfWeek); }, @@ -66,7 +69,6 @@ export const Stundenplan = { monthLastDay: function () { return this.calendarDateToString(this.eventCalendarDate.cdLastDayOfCalendarMonth); }, - }, methods:{ fetchStudiensemesterDetails: async function (date) { @@ -84,8 +86,37 @@ export const Stundenplan = { this.currentlySelectedEvent = event; }, selectDay: function(day){ + const date = day.getFullYear() + "-" + + String(day.getMonth() + 1).padStart(2, "0") + "-" + + String(day.getDate()).padStart(2, "0"); + + this.$router.replace({ + name: "Stundenplan", + params: { + mode: this.calendarMode, + focus_date: date, + lv_id: this.viewData?.lv_id || null + } + }) + this.currentDay = day; }, + handleChangeMode(mode) { + console.log('handleChangeMode', mode) + const modeCapitalized = mode.charAt(0).toUpperCase() + mode.slice(1) + + // TODO: clashes with initial mode and needs to be differentiated + // this.$router.replace({ + // name: "Stundenplan", + // params: { + // mode: modeCapitalized, + // focus_date: this.currentDay.toISOString().split("T")[0], + // lv_id: this.viewData?.lv_id || null + // } + // }) + + this.calendarMode = mode + }, showModal: function(event){ this.currentlySelectedEvent = event; Vue.nextTick(() => { @@ -163,7 +194,17 @@ export const Stundenplan = {

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


- +