diff --git a/application/config/routes.php b/application/config/routes.php index 798d29ad0..af6b563d3 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -62,6 +62,7 @@ $route['api/v1/ressource/[B|b]etriebsmittelperson/(:any)'] = 'api/v1/ressource/b $route['api/v1/system/[S|s]prache/(:any)'] = 'api/v1/system/sprache2/$1'; $route['Cis/LvPlan/.*'] = 'Cis/LvPlan/index/$1'; +$route['Cis/MyLvPlan/.*'] = 'Cis/MyLvPlan/index/$1'; // load routes from extensions $subdir = 'application/config/extensions'; diff --git a/application/controllers/Cis/MyLvPlan.php b/application/controllers/Cis/MyLvPlan.php new file mode 100644 index 000000000..366ce8e65 --- /dev/null +++ b/application/controllers/Cis/MyLvPlan.php @@ -0,0 +1,39 @@ + ['basis/cis:r'] + ]); + + // Load Config + $this->load->config('calendar'); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + + $viewData = array( + 'uid'=>getAuthUID(), + 'timezone' => $this->config->item('timezone') + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'MyLvPlan']); + } +} diff --git a/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js index 075a399d8..b3ffa4315 100644 --- a/public/js/apps/Dashboard/Fhc.js +++ b/public/js/apps/Dashboard/Fhc.js @@ -3,7 +3,8 @@ import PluginsPhrasen from '../../plugins/Phrasen.js'; import Theme from '../../plugin/Theme.js'; import contrast from '../../directives/contrast.js'; import {setScrollbarWidth} from "../../helpers/CssVarCalcHelpers.js"; -import LvPlan, {DEFAULT_MODE_LVPLAN} from "../../components/Cis/LvPlan/LvPlan.js"; +import LvPlan from "../../components/Cis/LvPlan/Lehrveranstaltung.js"; +import MyLvPlan from "../../components/Cis/LvPlan/Personal.js"; import MylvStudent from "../../components/Cis/Mylv/Student.js"; import Profil from "../../components/Cis/Profil/Profil.js"; import Raumsuche from "../../components/Cis/Raumsuche/Raumsuche.js"; @@ -154,10 +155,14 @@ const router = VueRouter.createRouter({ path: "/Cis/LvPlan/:lv_id(\\d+)", name: "LvPlanOld", component: LvPlan, - redirect: (to) => { + redirect(to) { + const route = Vue.unref(router.currentRoute); + const { mode, focus_date } = route.params; // keep mode and focus_date if available return { // redirect to longer LvPlan url and map params name: "LvPlan", params: { + mode, + focus_date, lv_id: to.params.lv_id }, }; @@ -167,42 +172,20 @@ const router = VueRouter.createRouter({ path: `/Cis/LvPlan/:mode?/:focus_date?/:lv_id?`, name: 'LvPlan', component: LvPlan, - props: (route) => { // validate and set mode/focus date if for some reason missing - const validModes = ["Month", "Week", "Day"]; - - // check mode string - const 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() - : DEFAULT_MODE_LVPLAN; - - // 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 + props(route) { return { - propsViewData: { - mode, - focus_date, - lv_id: route.params.lv_id - } + propsViewData: route.params + }; + } + }, + { + path: `/Cis/MyLvPlan/:mode?/:focus_date?`, + name: 'MyLvPlan', + component: MyLvPlan, + props(route) { + return { + propsViewData: route.params }; - }, - beforeEnter: (to, from, next) => { - // missing mode or focus_date -> set defaults - if (!to.params.mode || !to.params.focus_date) { - next({ - name: "LvPlan", - params: { - mode: to.params.mode || DEFAULT_MODE_LVPLAN, - focus_date: to.params.focus_date || new Date().toISOString().split("T")[0], - lv_id: to.params.lv_id - } - }); - } else { - next(); - } } }, { diff --git a/public/js/components/Cis/LvPlan/Lehrveranstaltung.js b/public/js/components/Cis/LvPlan/Lehrveranstaltung.js new file mode 100644 index 000000000..70773dce6 --- /dev/null +++ b/public/js/components/Cis/LvPlan/Lehrveranstaltung.js @@ -0,0 +1,96 @@ +import FhcCalendar from "../../Calendar/LvPlan.js"; + +import ApiLvPlan from '../../../api/factory/lvPlan.js'; +import ApiAuthinfo from '../../../api/factory/authinfo.js'; + +export const DEFAULT_MODE_LVPLAN = 'Week' + +export default { + name: 'LvPlanLehrveranstaltung', + components: { + FhcCalendar + }, + props: { + viewData: Object, // NOTE(chris): this is inherited from router-view + propsViewData: Object + }, + data() { + return { + lv: null + }; + }, + computed:{ + currentDay() { + if (!this.propsViewData?.focus_date || isNaN(new Date(this.propsViewData?.focus_date))) + return luxon.DateTime.now().setZone(this.viewData.timezone).toISODate(); + return this.propsViewData?.focus_date; + }, + currentMode() { + if (!this.propsViewData?.mode || !['day', 'week', 'month'].includes(this.propsViewData?.mode.toLowerCase())) + return DEFAULT_MODE_LVPLAN; + return this.propsViewData?.mode; + }, + currentLv() { + if (isNaN(parseInt(this.propsViewData?.lv_id))) + return null; + return this.propsViewData.lv_id; + } + }, + methods: { + handleChangeDate(day, newMode) { + return this.handleChangeMode(newMode, day); + }, + handleChangeMode(newMode, day) { + const mode = newMode[0].toUpperCase() + newMode.slice(1) + const focus_date = day.toISODate(); + + this.$router.push({ + name: "LvPlan", + params: { + mode, + focus_date, + lv_id: this.currentLv + } + }); + }, + getPromiseFunc(start, end) { + return [ + this.$api.call(ApiLvPlan.eventsLv(this.propsViewData.lv_id, start.toISODate(), end.toISODate())), + this.$api.call(ApiLvPlan.getLvPlanReservierungen(start.toISODate(), end.toISODate())) + ]; + } + }, + created() { + if (this.currentLv === null) + return; + this.$api + .call(ApiLvPlan.getLv(this.propsViewData?.lv_id)) + .then(res => { + this.lv = res.data; + }); + }, + template: /*html*/` +
+

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

+
+
+ {{ $p.t('lehre/noLvFound') }} +
+ +
` +}; diff --git a/public/js/components/Cis/LvPlan/Personal.js b/public/js/components/Cis/LvPlan/Personal.js new file mode 100644 index 000000000..5c4be5c23 --- /dev/null +++ b/public/js/components/Cis/LvPlan/Personal.js @@ -0,0 +1,143 @@ +import FhcCalendar from "../../Calendar/LvPlan.js"; + +import ApiLvPlan from '../../../api/factory/lvPlan.js'; +import ApiAuthinfo from '../../../api/factory/authinfo.js'; + +export const DEFAULT_MODE_LVPLAN = 'Week' + +export default { + name: 'LvPlanPersonal', + components: { + FhcCalendar + }, + props: { + viewData: Object, // NOTE(chris): this is inherited from router-view + propsViewData: Object + }, + data() { + return { + studiensemester_kurzbz: null, + studiensemester_start: null, + studiensemester_ende: null, + uid: null + }; + }, + computed:{ + currentDay() { + if (!this.propsViewData?.focus_date || isNaN(new Date(this.propsViewData?.focus_date))) + return luxon.DateTime.now().setZone(this.viewData.timezone).toISODate(); + return this.propsViewData?.focus_date; + }, + currentMode() { + if (!this.propsViewData?.mode || !['day', 'week', 'month'].includes(this.propsViewData?.mode.toLowerCase())) + return DEFAULT_MODE_LVPLAN; + return this.propsViewData?.mode; + }, + downloadLinks() { + if (!this.studiensemester_start || !this.studiensemester_ende || !this.uid) + return false; + + const opts = { zone: this.viewData.timezone }; + const start = luxon.DateTime + .fromISO(this.studiensemester_start, opts) + .toUnixInteger(); + const ende = luxon.DateTime + .fromISO(this.studiensemester_ende, opts) + .toUnixInteger(); + + const download_link = FHC_JS_DATA_STORAGE_OBJECT.app_root + + 'cis/private/lvplan/stpl_kalender.php' + + '?type=student' + + '&pers_uid=' + this.uid + + '&begin=' + start + + '&ende=' + ende; + + return [ + { title: "excel", icon: 'fa-solid fa-file-excel', link: download_link + '&format=excel' }, + { title: "csv", icon: 'fa-solid fa-file-csv', link: download_link + '&format=csv' }, + { title: "ical1", icon: 'fa-regular fa-calendar', link: download_link + '&format=ical&version=1&target=ical' }, + { title: "ical2", icon: 'fa-regular fa-calendar', link: download_link + '&format=ical&version=2&target=ical' } + ]; + } + }, + methods: { + handleChangeDate(day, newMode) { + return this.handleChangeMode(newMode, day); + }, + handleChangeMode(newMode, day) { + const mode = newMode[0].toUpperCase() + newMode.slice(1) + const focus_date = day.toISODate(); + + this.$router.push({ + name: "MyLvPlan", + params: { + mode, + focus_date + } + }); + }, + updateRange(rangeInterval) { + this.$api + .call(ApiLvPlan.studiensemesterDateInterval( + rangeInterval.end.startOf('week').toISODate() + )) + .then(res => { + this.studiensemester_kurzbz = res.data.studiensemester_kurzbz; + this.studiensemester_start = res.data.start; + this.studiensemester_ende = res.data.ende; + }); + }, + getPromiseFunc(start, end) { + return [ + this.$api.call(ApiLvPlan.eventsPersonal(start.toISODate(), end.toISODate())), + this.$api.call(ApiLvPlan.getLvPlanReservierungen(start.toISODate(), end.toISODate())) + ]; + } + }, + created() { + this.$api + .call(ApiAuthinfo.getAuthUID()) + .then(res => { + this.uid = res.data.uid; + }); + }, + template: /*html*/` +
+

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

+
+ + + +
` +};