From eabe8ef40139272d952fcbcdf4a9c242dae5de38 Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Tue, 11 Feb 2025 10:15:22 +0100 Subject: [PATCH 1/7] CalendarDate patch schaltjahr --- public/js/composables/CalendarDate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/composables/CalendarDate.js b/public/js/composables/CalendarDate.js index ff7b2916f..77dc07128 100644 --- a/public/js/composables/CalendarDate.js +++ b/public/js/composables/CalendarDate.js @@ -3,7 +3,7 @@ import CalendarDates from "./CalendarDates.js"; const monthDayRanges = [] for(let i = 1; i < 13; i++) { - monthDayRanges.push(new Date(1995, i, 0).getDate()) + monthDayRanges.push(new Date(new Date(Date.now).getFullYear(), i, 0).getDate()) } class CalendarDate { From fe4351fc8729fa9b8673b15a14193451b62113b6 Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Tue, 11 Feb 2025 11:23:50 +0100 Subject: [PATCH 2/7] lv info ort content link when content_id was expanded --- .../controllers/api/frontend/v1/Stundenplan.php | 17 +++++++++++++++++ public/js/components/Cis/Mylv/LvInfo.js | 3 +-- public/js/composables/CalendarDate.js | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/application/controllers/api/frontend/v1/Stundenplan.php b/application/controllers/api/frontend/v1/Stundenplan.php index 249f0fb3c..0a56dac71 100644 --- a/application/controllers/api/frontend/v1/Stundenplan.php +++ b/application/controllers/api/frontend/v1/Stundenplan.php @@ -278,6 +278,23 @@ class Stundenplan extends FHCAPI_Controller $gruppe_obj_array[] = $lv_gruppe_object; } + + if($item->ort_kurzbz) { + + $ort_content_object = $this->StundenplanModel->execReadOnlyQuery(" + SELECT content_id + FROM public.tbl_ort + WHERE ort_kurzbz = ?", [$item->ort_kurzbz]); + if (isError($ort_content_object)) { + $this->show_error(getError($ort_content_object)); + } + $ort_content_object = getData($ort_content_object)[0]; + if($ort_content_object) { + $item->ort_content_id = $ort_content_object->content_id; + } + + + } $item->gruppe = $gruppe_obj_array; $item->lektor = $lektor_obj_array; diff --git a/public/js/components/Cis/Mylv/LvInfo.js b/public/js/components/Cis/Mylv/LvInfo.js index e140a1a0b..df82f5cca 100644 --- a/public/js/components/Cis/Mylv/LvInfo.js +++ b/public/js/components/Cis/Mylv/LvInfo.js @@ -24,8 +24,7 @@ export default { { if (!this.event || !this.event.ort_content_id) return "a"; - // TODO: define/build link with content_id and/or roomname - // return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + `/CisVue/cms/content/${this.event.ort_content_id}` + return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + `/CisVue/Cms/content/${this.event.ort_content_id}` }, start_time: function () { if (!this.event.start) return 'N/A'; diff --git a/public/js/composables/CalendarDate.js b/public/js/composables/CalendarDate.js index 77dc07128..f2f8c93f0 100644 --- a/public/js/composables/CalendarDate.js +++ b/public/js/composables/CalendarDate.js @@ -3,7 +3,7 @@ import CalendarDates from "./CalendarDates.js"; const monthDayRanges = [] for(let i = 1; i < 13; i++) { - monthDayRanges.push(new Date(new Date(Date.now).getFullYear(), i, 0).getDate()) + monthDayRanges.push(new Date(new Date(Date.now()).getFullYear(), i, 0).getDate()) } class CalendarDate { From 2b27b55f40902763b4721ee58139609dd630dae3 Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Tue, 11 Feb 2025 15:05:22 +0100 Subject: [PATCH 3/7] attempt sanitizing raum content when content is just h1 + img tag; sanitize tables on raum contents sites --- .../Cms/Content_types/Raum_contentmittitel.js | 85 ++++++++++++++++++- 1 file changed, 81 insertions(+), 4 deletions(-) diff --git a/public/js/components/Cis/Cms/Content_types/Raum_contentmittitel.js b/public/js/components/Cis/Cms/Content_types/Raum_contentmittitel.js index 5e3bdb2ad..6f920e007 100644 --- a/public/js/components/Cis/Cms/Content_types/Raum_contentmittitel.js +++ b/public/js/components/Cis/Cms/Content_types/Raum_contentmittitel.js @@ -1,6 +1,11 @@ export default { name: "RaumComponent", + data() { + return { + imgContent: null + } + }, props:{ content:{ type:String, @@ -10,11 +15,64 @@ export default { type:Number, } }, + methods: { + sanitizeLegacyTables(table) { + + // find nested tables and replace with p element + const tt = table.querySelectorAll('table') + tt.forEach(t => { + const textContent = t.textContent.trim(); + const pElement = document.createElement('p'); + pElement.textContent = textContent; + t.parentNode.replaceChild(pElement, t); + }) + + // find unordered lists, traverse li childs and replace with p element -> more readable than 1 p tag for ul + const ul = table.querySelectorAll('ul') + ul.forEach(u => { + Array.from(u.children).forEach(li => { + const p = document.createElement('p'); + p.textContent = li.textContent + u.parentNode.appendChild(p) + }) + u.parentNode.removeChild(u) + + }) + + // find bare text nodes and put into p element + const td = Array.from(table.querySelectorAll('td')).filter(el => el.scrollWidth > 100) + td.forEach(element => { + if (element.firstChild?.nodeType === Node.TEXT_NODE && element.firstChild.length > 10) { + const p = document.createElement('p'); + p.appendChild(element.firstChild) + element.appendChild(p); + } + }); + + // flatten nested th elements + const ths = Array.from(table.querySelectorAll('th')) + ths.forEach(th => { + + if(th.children.length > 1) { + th.innerHTML = Array.from(th.childNodes).find(cn => cn.textContent).textContent + } + }) + + // let p elements wrap on overflow + const p = table.querySelectorAll('p') + p.forEach(p => { + p.style.setProperty('word-wrap', 'break-word'); + p.style.setProperty('white-space', 'normal'); + p.style.setProperty('max-width', '400px'); + }) + } + }, mounted(){ // replaces the tablesorter with the tabulator let tables = document.getElementsByClassName("tablesorter"); - + for (let table of tables) { + this.sanitizeLegacyTables(table) new Tabulator(table, { layout: "fitDataStretch", @@ -25,11 +83,28 @@ export default { } }) } + + + const parser = new DOMParser() + const doc = parser.parseFromString(`
${this.content}
`, "text/html"); + + const img = doc.querySelector("img") + // let img = document.getElementsByTagName("img"); + if(img && img.title) + { + const imgAttributes = {} + for (let attr of img.attributes) { + imgAttributes[attr.name] = attr.value + } - // tries to wrap the Raum titel with a link tag that redirects to the Reservierungen of that Raum + this.imgContent = imgAttributes; // Now it's a plain object + return + } + let title = document.getElementsByTagName("h1"); title = title.length ? title[0] : null; - if (title) + // tries to wrap the Raum titel with a link tag that redirects to the Reservierungen of that Raum + if (title && title.innerText) { let room_name = title.innerText; let room_name_reg_exp = new RegExp("\\w*\\s([a-zA-Z][0-9\\.]+)$"); @@ -56,7 +131,9 @@ export default { }, template: /*html*/ ` -
+ +
+

Content was not found

`, }; From bdb312cf56fc1463864bf61892f76ef7b13cf0d7 Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Tue, 11 Feb 2025 15:16:07 +0100 Subject: [PATCH 4/7] img parse only after usual procedure failed --- .../Cms/Content_types/Raum_contentmittitel.js | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/public/js/components/Cis/Cms/Content_types/Raum_contentmittitel.js b/public/js/components/Cis/Cms/Content_types/Raum_contentmittitel.js index 6f920e007..d7b9ed956 100644 --- a/public/js/components/Cis/Cms/Content_types/Raum_contentmittitel.js +++ b/public/js/components/Cis/Cms/Content_types/Raum_contentmittitel.js @@ -84,23 +84,6 @@ export default { }) } - - const parser = new DOMParser() - const doc = parser.parseFromString(`
${this.content}
`, "text/html"); - - const img = doc.querySelector("img") - // let img = document.getElementsByTagName("img"); - if(img && img.title) - { - const imgAttributes = {} - for (let attr of img.attributes) { - imgAttributes[attr.name] = attr.value - } - - this.imgContent = imgAttributes; // Now it's a plain object - return - } - let title = document.getElementsByTagName("h1"); title = title.length ? title[0] : null; // tries to wrap the Raum titel with a link tag that redirects to the Reservierungen of that Raum @@ -123,11 +106,25 @@ export default { console.error(`the regular expression did not match the room name: ${room_name}`); } + return } - else + + const parser = new DOMParser() + const doc = parser.parseFromString(`
${this.content}
`, "text/html"); + + const img = doc.querySelector("img") + if(img && img.title) { - console.error(`was not able to get the title of the raum_contentmittitel by searching for the first h1 element`); + const imgAttributes = {} + for (let attr of img.attributes) { + imgAttributes[attr.name] = attr.value + } + + this.imgContent = imgAttributes } + + console.error(`was not able to get the title of the raum_contentmittitel`); + }, template: /*html*/ ` From bcb88c0cb7691475060339634a6318a07ffafc14 Mon Sep 17 00:00:00 2001 From: SimonGschnell Date: Wed, 12 Feb 2025 11:11:10 +0100 Subject: [PATCH 5/7] refactor(Calendar Month View): instead of using border when highlighting the current day, uses box-shadow so that the content inside the highlighted day does not shift because of the width of the additional border --- public/css/components/calendar.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/public/css/components/calendar.css b/public/css/components/calendar.css index 4657bbb3f..9be771adf 100644 --- a/public/css/components/calendar.css +++ b/public/css/components/calendar.css @@ -203,8 +203,7 @@ } .fhc-highlight-day { - border-width: 2px !important; - border-color: black !important; + box-shadow: inset 0 0 0 2px black !important; } .fhc-calendar-sm .fhc-calendar-month-page-day.active .no, From 8525c823057f51ba30d064f3658b97d5cdf6e3bf Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Wed, 12 Feb 2025 11:56:12 +0100 Subject: [PATCH 6/7] set menuEntry href based on link form -> no href on menus without full url, hash links on menus dont trigger routing anymore; news widget check if carousel exists on mounted nextTick; --- public/js/apps/Dashboard/Fhc.js | 15 ++++++++++++--- public/js/components/Cis/Menu/Entry.js | 7 +++++-- public/js/components/DashboardWidget/News.js | 12 +++++++----- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js index 8d7f9888b..6a3f8c66d 100644 --- a/public/js/apps/Dashboard/Fhc.js +++ b/public/js/apps/Dashboard/Fhc.js @@ -98,11 +98,12 @@ const app = Vue.createApp({ const target = event.target.closest('a'); if (target && this.isInternalRoute(target.href)) { + const url = new URL(target.href) - const path = new URL(target.href).pathname + const path = url.pathname const base = this.$router.options.history.base const route = path.replace(base, '') || '/' - + // let click event propagate normally if we dont route internally const res = this.$router.resolve(route) if(!res?.matched?.length) return @@ -112,10 +113,13 @@ const app = Vue.createApp({ if(this.isMobile) { // toggle the menu const navMain = document.getElementById('nav-main'); // fix unwanted toggle from off to on for some links on mobile - if(navMain.classList.contains('show')) document.getElementById('nav-main-btn').click(); + if(navMain.classList.contains('show')){ + document.getElementById('nav-main-btn').click(); + } } this.$router.push(route); + } } }, @@ -127,6 +131,11 @@ const app = Vue.createApp({ }, }); +router.beforeEach((to,from) => { + console.log('to', to) + console.log('from', from) +}) + // kind of a bandaid for bad css on some pages to avoid horizontal scroll setScrollbarWidth(); app.use(router); diff --git a/public/js/components/Cis/Menu/Entry.js b/public/js/components/Cis/Menu/Entry.js index 982777e60..cc4ad2df5 100644 --- a/public/js/components/Cis/Menu/Entry.js +++ b/public/js/components/Cis/Menu/Entry.js @@ -74,7 +74,7 @@ export default { return ''; let xmlDoc = (new DOMParser()).parseFromString(this.entry.content,"text/xml"); let url = xmlDoc.getElementsByTagName('url')[0]; - + if (!url) return ''; // TODO(chris): replace get params @@ -101,6 +101,9 @@ export default { } return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/CisVue/Cms/content/' + this.entry.content_id; }, + hasFullLink() { + return this.link.startsWith(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router) + }, target() { if (this.entry.template_kurzbz == 'redirect') { if (!this.entry.content) @@ -201,7 +204,7 @@ export default {