diff --git a/application/controllers/api/frontend/v1/LvMenu.php b/application/controllers/api/frontend/v1/LvMenu.php index 068eaf580..6bad00e1e 100644 --- a/application/controllers/api/frontend/v1/LvMenu.php +++ b/application/controllers/api/frontend/v1/LvMenu.php @@ -67,7 +67,7 @@ class LvMenu extends FHCAPI_Controller $lvMenuOptionList = $this->input->post('lvMenuOptionList', true); $result =[]; foreach($lvMenuOptionList as $lvMenuOptions){ - $lvMenu = $this->getLvMenu($lvMenuOptions['lvid'],$lvMenuOptions['studiensemester_kurzbz']); + $lvMenu = $this->getLvMenuInternal($lvMenuOptions['lvid'],$lvMenuOptions['studiensemester_kurzbz']); $result[$lvMenuOptions['lvid']]=$lvMenu; } diff --git a/public/js/components/Cis/Mylv/MyLv.js b/public/js/components/Cis/Mylv/MyLv.js index b4b5f1a6b..9f659a3cc 100644 --- a/public/js/components/Cis/Mylv/MyLv.js +++ b/public/js/components/Cis/Mylv/MyLv.js @@ -17,14 +17,12 @@ export default { studiensemester: null, lvs: {}, currentSemester: null, - lvMenues: null, mode: 'table' // TODO: load from local storage }; }, provide() { return { type: Vue.computed(() => this.type), - lvMenues: Vue.computed(() => this.lvMenues) } }, inject: ['isStudent', 'isMitarbeiter'], @@ -50,7 +48,14 @@ export default { this.firstLoad = false; this.$api.call(ApiAddons.getMultipleLvMenu(this.lvs[this.currentSemester].lvs, this.currentSemester)).then(res => { - this.lvMenues = res.data + if(res.data) { + Object.entries(res.data).forEach((entry) => { + // entry[0] -> key -> lvid + // entry[1] -> value -> menu + const lv = this.lvs[this.currentSemester].lvs.find(lv => lv.lehrveranstaltung_id == entry[0]) + lv.menu = entry[1] + }) + } }) }) diff --git a/public/js/components/Cis/Mylv/Table.js b/public/js/components/Cis/Mylv/Table.js index f1b624b01..09c1b83ab 100644 --- a/public/js/components/Cis/Mylv/Table.js +++ b/public/js/components/Cis/Mylv/Table.js @@ -25,9 +25,9 @@ export default { {title: Vue.computed(() => this.$p.t('lehre/studiengang')), field: 'sg_bezeichnung', widthGrow: 1}, {title: Vue.computed(() => this.$p.t('global/bezeichnung')), field: 'bezeichnung', widthGrow: 2}, {title: Vue.computed(() => this.$p.t('lehre/orgform')), field: 'orgform_kurzbz', widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('admission/stg_kurz')), field: 'studiengang_kuerzel', widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('global/actions')), - field: 'menu', formatter: this.actionFormatter, widthGrow: 1} + {title: Vue.computed(() => this.$p.t('lehre/kurzbz')), field: 'studiengang_kuerzel', widthGrow: 1}, + {title: Vue.computed(() => this.$p.t('global/actions')), headerSort: false, + field: 'menu', formatter: this.actionFormatter, widthGrow: 1, tooltip: this.spoofingFunc} ], persistence: false, persistenceID: "mylv_2026_04_17" @@ -47,23 +47,86 @@ export default { }, methods: { + spoofingFunc() { + // intentionally send empty tooltip info so tabulator tooltip doesnt get rendered but hover event propagates + // to individual button tooltips + return '' + }, + c4_target(menuItem) { + if (menuItem.c4_moodle_links?.length > 0) return null; + return menuItem.c4_target ?? null; + }, + c4_link(menuItem) { + if (!menuItem) return null; + if (Array.isArray(menuItem.c4_moodle_links) && menuItem.c4_moodle_links.length) { + return '#'; + } else { + return menuItem.c4_link ?? null; + } + }, handleUuidDefined(uuid) { this.tabulatorUuid = uuid }, tableResolve(resolve) { this.tableBuiltResolve = resolve }, - actionFormatter() { - return '' + actionFormatter(cell, formatterParams, onRendered) { + let container = document.createElement('div'); + container.className = "d-flex gap-2"; + + const data = cell.getData() + console.log(data) + if(data.menu && data.menu.length) { + + const calculatedMinWidth = data.menu.length * 120; + container.style.minWidth = `${calculatedMinWidth}px`; + const abbreviate = (str, limit = 12) => + str.length > limit + 3 ? `${str.slice(0, limit)}...` : str; + + data.menu.forEach((lvLink) => { + let button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + if (!lvLink.c4_link) { + button.classList.add('unavailable'); + } + const icon = lvLink.c4_icon2 ?? 'fa-solid fa-pen-to-square' + button.id = lvLink.name + button.innerHTML = ''; + + button.title = lvLink.phrase ? this.$p.t(lvLink.phrase) : lvLink.name; + button.innerHTML += ''+abbreviate(button.title)+''; + button.addEventListener('click', (event) => { + // replicate a tag here + event.preventDefault(); + const url = this.c4_link(lvLink); + if (url) { + const target = lvLink.c4_target || '_blank'; + + if (target === '_blank') { + window.open(url, '_blank', 'noopener,noreferrer'); + } else { + window.location.href = url; + } + } else { + console.warn("Link is unavailable for:", lvLink.name); + } + }); + container.append(button); + }) + + } + + return container; }, async setupData() { this.$refs.mylvTable.tabulator.setData(this.lvs); }, async setupMounted() { - + // console.log('mounted pre table promise') this.tableBuiltPromise = new Promise(this.tableResolve) await this.tableBuiltPromise + console.log('mounted post table promise') this.setupData() const tableID = this.tabulatorUuid ? ('-' + this.tabulatorUuid) : '' @@ -85,6 +148,18 @@ export default { mounted() { this.setupMounted() }, + watch: { + lvs: { + handler(newVal, oldVal) { + console.log('watcher') + if(this.$refs.mylvTable) { + console.log('watcher inside if ref table clause') + this.$refs.mylvTable.tabulator.setData(newVal); + } + }, + deep: true + } + }, template: `