From d4feee89142fc6bcbf1222549b5a088376e87225 Mon Sep 17 00:00:00 2001 From: Cristina Date: Tue, 18 Mar 2025 14:30:19 +0100 Subject: [PATCH 01/40] Fixed wrong param causing wrong Notenliste for Wiederholer --- cis/private/lehre/notenliste.xls.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cis/private/lehre/notenliste.xls.php b/cis/private/lehre/notenliste.xls.php index 6c8db5246..c525b2d6c 100644 --- a/cis/private/lehre/notenliste.xls.php +++ b/cis/private/lehre/notenliste.xls.php @@ -339,7 +339,7 @@ else { $worksheet->write($lines,8, trim($elem->matrikelnr), $format_highlight); $pr = new Pruefung(); - $pr->getPruefungen($elem->uid, "Termin2", $lvid, $sem); + $pr->getPruefungen($elem->uid, "Termin2", $lvid, $stsem); $output2 = $pr->result; if ($output2) @@ -360,7 +360,7 @@ else { $worksheet->write($lines,12, trim($elem->matrikelnr), $format_highlight); $pr = new Pruefung(); - $pr->getPruefungen($elem->uid, "Termin3", $lvid, $sem); + $pr->getPruefungen($elem->uid, "Termin3", $lvid, $stsem); $output3 = $pr->result; if ($output3) From 67281c84ed27dc6fbb9cc8157f81f340ea973a7a Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 8 Oct 2025 13:36:20 +0200 Subject: [PATCH 02/40] FhcApps Library --- public/js/FhcApps.js | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 public/js/FhcApps.js diff --git a/public/js/FhcApps.js b/public/js/FhcApps.js new file mode 100644 index 000000000..f9ec61001 --- /dev/null +++ b/public/js/FhcApps.js @@ -0,0 +1,50 @@ +/** + * Copyright (C) 2025 fhcomplete.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +const FhcApps = (function() { + // Logic to extend app here (like adding components, plugins, ...) + + function makeExtendable(app) { + // apply extensions here + return app; + } + + return { + makeExtendable + }; +})(); + +FhcApps.router = (() => { + const extraRoutes = []; + + function addRoute(...route) { + extraRoutes.push(route); + } + + function makeExtendable(router) { + while (extraRoutes.length) { + router.addRoute(...extraRoutes.shift()); + } + router.replace(router.currentRoute.value.fullPath); + } + + return { + addRoute, + makeExtendable + }; +})(); From 842dabc1e7aac7817303aacf0105a7ed8ba24257 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 8 Oct 2025 13:37:06 +0200 Subject: [PATCH 03/40] add fhcApps functionality to view template --- application/views/templates/FHC-Common.php | 57 ++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/application/views/templates/FHC-Common.php b/application/views/templates/FHC-Common.php index 71f9c46c4..955583500 100644 --- a/application/views/templates/FHC-Common.php +++ b/application/views/templates/FHC-Common.php @@ -48,3 +48,60 @@ $udfs = isset($udfs) ? $udfs : false; $widgets = isset($widgets) ? $widgets : false; $tags = isset($tags) ? $tags : false; + +// VueJs App magic +if (isset($fhcApps)) { + if (!isset($customJSs)) + $customJSs = ['public/js/FhcApps.js']; + elseif (!is_array($customJSs)) + $customJSs = [$customJSs, 'public/js/FhcApps.js']; + else + array_push($customJSs, 'public/js/FhcApps.js'); + + if (!isset($customJSModules)) + $customJSModules = []; + elseif (!is_array($customJSModules)) + $customJSModules = [$customJSModules]; + + if (!isset($customCSSs)) + $customCSSs = []; + elseif (!is_array($customCSSs)) + $customCSSs = [$customCSSs]; + + $ext_path = 'public/extensions/'; + $ext_realpath = str_replace('/', DIRECTORY_SEPARATOR, $ext_path); + + foreach ($fhcApps as $app) { + if (!strstr($app, ':')) { + $app_js_path = 'public/js/apps/' . $app . '.js'; + $app_css_path = 'public/css/apps/' . $app . '.css'; + $app_js_ext_path = '/js/extend_app/' . $app . '.js'; + $app_css_ext_path = '/css/extend_app/' . $app . '.css'; + } else { + list($ext_name, $app_path) = explode(':', $app); + $app_js_path = 'public/extensions/' . $ext_name . '/js/apps/' . $app_path . '.js'; + $app_css_path = 'public/extensions/' . $ext_name . '/css/apps/' . $app_path . '.css'; + $app_js_ext_path = '/js/extend_app/extensions/' . $ext_name . '/' . $app_path . '.js'; + $app_css_ext_path = '/css/extend_app/extensions/' . $ext_name . '/' . $app_path . '.css'; + } + + if (file_exists(FHCPATH . str_replace('/', DIRECTORY_SEPARATOR, $app_css_path))) + array_push($customCSSs, $app_css_path); + + foreach (scandir(FHCPATH . $ext_realpath) as $extension_name) { + if ($extension_name[0] == '.') + continue; + + $app_js_ext_realpath = str_replace('/', DIRECTORY_SEPARATOR, $app_js_ext_path); + if (file_exists(FHCPATH . $ext_realpath . $extension_name . $app_js_ext_realpath)) { + array_push($customJSModules, $ext_path . $extension_name . $app_js_ext_path); + } + $app_css_ext_realpath = str_replace('/', DIRECTORY_SEPARATOR, $app_css_ext_path); + if (file_exists(FHCPATH . $ext_realpath . $extension_name . $app_css_ext_realpath)) { + array_push($customCSSs, $ext_path . $extension_name . $app_css_ext_path); + } + } + + array_push($customJSModules, $app_js_path); + } +} From d2f21ba4e6fe7aee20fcafdd732c256b653e58d8 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 8 Oct 2025 14:45:12 +0200 Subject: [PATCH 04/40] use fhcApps for LVVerwaltung --- application/views/LVVerwaltung.php | 4 ++-- public/js/apps/LVVerwaltung.js | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/application/views/LVVerwaltung.php b/application/views/LVVerwaltung.php index 4cebae839..5c4c9549e 100644 --- a/application/views/LVVerwaltung.php +++ b/application/views/LVVerwaltung.php @@ -17,8 +17,8 @@ 'public/css/Lvverwaltung.css' ], - 'customJSModules' => [ - 'public/js/apps/LVVerwaltung.js' + 'fhcApps' => [ + 'LVVerwaltung' ] ); diff --git a/public/js/apps/LVVerwaltung.js b/public/js/apps/LVVerwaltung.js index f365b74a8..18f8a072f 100644 --- a/public/js/apps/LVVerwaltung.js +++ b/public/js/apps/LVVerwaltung.js @@ -89,8 +89,12 @@ const router = VueRouter.createRouter({ ] }); +FhcApps.router.makeExtendable(router); + const app = Vue.createApp(); +FhcApps.makeExtendable(app); + app .use(router) .use(primevue.config.default, { From 09864c515428e7901b32ba9d568ae447ff0f7989 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 9 Oct 2025 08:41:58 +0200 Subject: [PATCH 05/40] remove unused view that links to a non existing app --- application/views/Cis/Profil.php | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 application/views/Cis/Profil.php diff --git a/application/views/Cis/Profil.php b/application/views/Cis/Profil.php deleted file mode 100644 index f66ebf8a9..000000000 --- a/application/views/Cis/Profil.php +++ /dev/null @@ -1,18 +0,0 @@ - 'Profil', - 'customJSModules' => ['public/js/apps/Cis/Profil.js'], - 'tabulator5' => true, - 'primevue3' => true, - 'customCSSs' => ['public/css/components/calendar.css', 'public/css/components/FilterComponent.css','public/css/components/Profil.css','public/css/components/FormUnderline.css'], - -); - -$this->load->view('templates/CISVUE-Header', $includesArray); -?> - -
- -
- -load->view('templates/CISVUE-Footer', $includesArray); ?> From d389cf87b8b7f31054552e53360fa8c7d78c56e4 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 9 Oct 2025 08:42:29 +0200 Subject: [PATCH 06/40] delete MyLv->Info because app does not exist anymore and url is rerouted to MyLv->index --- application/controllers/Cis/MyLv.php | 5 ----- application/views/Cis/LvInfo.php | 15 --------------- 2 files changed, 20 deletions(-) delete mode 100644 application/views/Cis/LvInfo.php diff --git a/application/controllers/Cis/MyLv.php b/application/controllers/Cis/MyLv.php index 49a938553..819d56b05 100644 --- a/application/controllers/Cis/MyLv.php +++ b/application/controllers/Cis/MyLv.php @@ -33,9 +33,4 @@ class MyLv extends Auth_Controller $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'MyLv']); } - - public function Info($studien_semester,$lvid) - { - $this->load->view('Cis/LvInfo',['lvid'=> $lvid, 'studien_semester' => $studien_semester]); - } } diff --git a/application/views/Cis/LvInfo.php b/application/views/Cis/LvInfo.php deleted file mode 100644 index 49a7b7a85..000000000 --- a/application/views/Cis/LvInfo.php +++ /dev/null @@ -1,15 +0,0 @@ - 'LvInfo', - 'customJSModules' => ['public/js/apps/Cis/LvInfo.js'] -); - -$this->load->view('templates/CISVUE-Header', $includesArray); -?> - -
- - -
- -load->view('templates/CISVUE-Footer', $includesArray); ?> From 3c3e92057317877cfb5e6da90fee8e31111a340b Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 9 Oct 2025 08:43:12 +0200 Subject: [PATCH 07/40] use fhcApps for Studentenverwaltung --- application/views/Studentenverwaltung.php | 4 ++-- public/js/apps/Studentenverwaltung.js | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/application/views/Studentenverwaltung.php b/application/views/Studentenverwaltung.php index 01e611657..aa4891e9a 100644 --- a/application/views/Studentenverwaltung.php +++ b/application/views/Studentenverwaltung.php @@ -26,8 +26,8 @@ #'vendor/npm-asset/primevue/tree/tree.min.js', #'vendor/npm-asset/primevue/toast/toast.min.js' ], - 'customJSModules' => [ - 'public/js/apps/Studentenverwaltung.js' + 'fhcApps' => [ + 'Studentenverwaltung' ] ); diff --git a/public/js/apps/Studentenverwaltung.js b/public/js/apps/Studentenverwaltung.js index 5eda16dd6..50763ad6f 100644 --- a/public/js/apps/Studentenverwaltung.js +++ b/public/js/apps/Studentenverwaltung.js @@ -168,10 +168,14 @@ router.afterEach((to, from, failure) => { document.title = title; }); +FhcApps.router.makeExtendable(router); + const app = Vue.createApp({ name: 'StudentenverwaltungApp' }); +FhcApps.makeExtendable(app); + app .use(router) .use(primevue.config.default, { From 0309c04ae09fb0b634d84ede9d0a66972ed435ca Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 9 Oct 2025 08:46:09 +0200 Subject: [PATCH 08/40] use fhcApps for Cis/Documents --- application/views/Cis/Documents.php | 2 +- public/js/apps/Cis/Documents.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/application/views/Cis/Documents.php b/application/views/Cis/Documents.php index f34ce3fc1..fa491fa11 100644 --- a/application/views/Cis/Documents.php +++ b/application/views/Cis/Documents.php @@ -2,7 +2,7 @@ $includesArray = array( 'title' => 'Documents', 'tabulator5' => true, - 'customJSModules' => ['public/js/apps/Cis/Documents.js'] + 'fhcApps' => ['Cis/Documents'] ); $this->load->view('templates/CISVUE-Header', $includesArray); diff --git a/public/js/apps/Cis/Documents.js b/public/js/apps/Cis/Documents.js index de03769b4..149a32446 100644 --- a/public/js/apps/Cis/Documents.js +++ b/public/js/apps/Cis/Documents.js @@ -87,6 +87,8 @@ const app = Vue.createApp({ } }); +FhcApps.makeExtendable(app); + setScrollbarWidth(); app.use(PluginsPhrasen); From ea0b69d4c274ea5f67854d058e8cc630423da720 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 9 Oct 2025 09:15:26 +0200 Subject: [PATCH 09/40] use fhcApps for ProfilUpdateRequest --- application/views/Cis/ProfilUpdate.php | 4 ++-- public/js/apps/Cis/ProfilUpdateRequests.js | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/application/views/Cis/ProfilUpdate.php b/application/views/Cis/ProfilUpdate.php index e797d436f..525d261a7 100644 --- a/application/views/Cis/ProfilUpdate.php +++ b/application/views/Cis/ProfilUpdate.php @@ -6,8 +6,8 @@ $includesArray = array( 'fontawesome6'=> true, 'axios027' => true, 'tabulator5' => true, - 'customJSModules' => array( - 'public/js/apps/Cis/ProfilUpdateRequests.js' + 'fhcApps' => array( + 'Cis/ProfilUpdateRequests' ), 'customCSSs' => array( 'public/css/components/FilterComponent.css','public/css/components/FormUnderline.css' diff --git a/public/js/apps/Cis/ProfilUpdateRequests.js b/public/js/apps/Cis/ProfilUpdateRequests.js index 68465b202..974b2c362 100644 --- a/public/js/apps/Cis/ProfilUpdateRequests.js +++ b/public/js/apps/Cis/ProfilUpdateRequests.js @@ -34,4 +34,7 @@ const app = Vue.createApp({ }); }, }); + +FhcApps.makeExtendable(app); + app.use(PluginsPhrasen).mount("#content"); \ No newline at end of file From 61600e78b630a3adac25b6f6ba0c9c005025ed3c Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 9 Oct 2025 09:27:31 +0200 Subject: [PATCH 10/40] use fhcApps for Bismeldestichtag/Bismeldestichtag --- application/views/codex/bismeldestichtag.php | 2 +- public/js/apps/Bismeldestichtag/Bismeldestichtag.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/application/views/codex/bismeldestichtag.php b/application/views/codex/bismeldestichtag.php index 37af16cc6..2f024d25e 100644 --- a/application/views/codex/bismeldestichtag.php +++ b/application/views/codex/bismeldestichtag.php @@ -10,7 +10,7 @@ 'tabulator5' => true, 'customCSSs' => array('vendor/vuejs/vuedatepicker_css/main.css'), 'customJSs' => array('vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js'), - 'customJSModules' => array('public/js/apps/Bismeldestichtag/Bismeldestichtag.js') + 'fhcApps' => array('Bismeldestichtag/Bismeldestichtag') ); $this->load->view('templates/FHC-Header', $includesArray); diff --git a/public/js/apps/Bismeldestichtag/Bismeldestichtag.js b/public/js/apps/Bismeldestichtag/Bismeldestichtag.js index d6e5a4a27..9a9766690 100644 --- a/public/js/apps/Bismeldestichtag/Bismeldestichtag.js +++ b/public/js/apps/Bismeldestichtag/Bismeldestichtag.js @@ -237,4 +237,6 @@ const bismeldestichtagApp = Vue.createApp({ } }); +FhcApps.makeExtendable(bismeldestichtagApp); + bismeldestichtagApp.use(PluginsPhrasen).mount('#main'); From d88cc77a5cb35cbc3c4b2cad034a9d2b896299c7 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 9 Oct 2025 10:40:02 +0200 Subject: [PATCH 11/40] use fhcApps for Studstatus --- application/views/lehre/Antrag/Create.php | 2 +- application/views/lehre/Antrag/Leitung/List.php | 2 +- application/views/lehre/Antrag/Student/List.php | 2 +- application/views/lehre/Antrag/Wiederholung/Student.php | 2 +- public/js/apps/lehre/Antrag.js | 3 +++ public/js/apps/lehre/Antrag/Leitung.js | 3 +++ public/js/apps/lehre/Antrag/Lvzuweisung.js | 3 +++ public/js/apps/lehre/Antrag/Student.js | 3 +++ 8 files changed, 16 insertions(+), 4 deletions(-) diff --git a/application/views/lehre/Antrag/Create.php b/application/views/lehre/Antrag/Create.php index 00e41d1cd..36a39078f 100644 --- a/application/views/lehre/Antrag/Create.php +++ b/application/views/lehre/Antrag/Create.php @@ -8,7 +8,7 @@ $sitesettings = array( 'fontawesome6' => true, 'phrases' => array( ), - 'customJSModules' => array('public/js/apps/lehre/Antrag.js'), + 'fhcApps' => array('lehre/Antrag'), 'customCSSs' => array( 'public/css/Fhc.css', 'public/css/components/primevue.css', diff --git a/application/views/lehre/Antrag/Leitung/List.php b/application/views/lehre/Antrag/Leitung/List.php index 1225b16b6..b1ba44a4c 100644 --- a/application/views/lehre/Antrag/Leitung/List.php +++ b/application/views/lehre/Antrag/Leitung/List.php @@ -18,7 +18,7 @@ $sitesettings = array( 'lehre', 'person', ), - 'customJSModules' => array('public/js/apps/lehre/Antrag/Leitung.js'), + 'fhcApps' => array('lehre/Antrag/Leitung'), 'customCSSs' => array( 'public/css/Fhc.css', 'public/css/components/primevue.css', diff --git a/application/views/lehre/Antrag/Student/List.php b/application/views/lehre/Antrag/Student/List.php index 6d769dafe..9454e2006 100644 --- a/application/views/lehre/Antrag/Student/List.php +++ b/application/views/lehre/Antrag/Student/List.php @@ -8,7 +8,7 @@ $sitesettings = array( 'fontawesome6' => true, 'phrases' => array( ), - 'customJSModules' => array('public/js/apps/lehre/Antrag/Student.js'), + 'fhcApps' => array('lehre/Antrag/Student'), 'customCSSs' => array( 'public/css/Fhc.css', 'public/css/components/primevue.css', diff --git a/application/views/lehre/Antrag/Wiederholung/Student.php b/application/views/lehre/Antrag/Wiederholung/Student.php index e51cfd1bc..73405fc0a 100644 --- a/application/views/lehre/Antrag/Wiederholung/Student.php +++ b/application/views/lehre/Antrag/Wiederholung/Student.php @@ -12,7 +12,7 @@ $sitesettings = array( 'lehre', 'global' ), - 'customJSModules' => array('public/js/apps/lehre/Antrag/Lvzuweisung.js'), + 'fhcApps' => array('lehre/Antrag/Lvzuweisung'), 'customCSSs' => array( 'public/css/Fhc.css', 'public/css/components/primevue.css', diff --git a/public/js/apps/lehre/Antrag.js b/public/js/apps/lehre/Antrag.js index 97b4bda97..afdfe48ab 100644 --- a/public/js/apps/lehre/Antrag.js +++ b/public/js/apps/lehre/Antrag.js @@ -20,6 +20,9 @@ const app = Vue.createApp({ }; } }); + +FhcApps.makeExtendable(app); + app .use(PluginsPhrasen) .mount('#wrapper'); \ No newline at end of file diff --git a/public/js/apps/lehre/Antrag/Leitung.js b/public/js/apps/lehre/Antrag/Leitung.js index 8fd8b117e..c8169629a 100644 --- a/public/js/apps/lehre/Antrag/Leitung.js +++ b/public/js/apps/lehre/Antrag/Leitung.js @@ -7,6 +7,9 @@ const app = Vue.createApp({ StudierendenantragLeitung } }); + +FhcApps.makeExtendable(app); + app .use(PluginsPhrasen) .use(primevue.config.default,{zIndex: {overlay: 9999}}) diff --git a/public/js/apps/lehre/Antrag/Lvzuweisung.js b/public/js/apps/lehre/Antrag/Lvzuweisung.js index 7504e7dcf..f85a52f62 100644 --- a/public/js/apps/lehre/Antrag/Lvzuweisung.js +++ b/public/js/apps/lehre/Antrag/Lvzuweisung.js @@ -12,6 +12,9 @@ const app = Vue.createApp({ } } }); + +FhcApps.makeExtendable(app); + app .use(PluginsPhrasen) .mount('#wrapper'); \ No newline at end of file diff --git a/public/js/apps/lehre/Antrag/Student.js b/public/js/apps/lehre/Antrag/Student.js index 46150c541..7d40f4339 100644 --- a/public/js/apps/lehre/Antrag/Student.js +++ b/public/js/apps/lehre/Antrag/Student.js @@ -7,6 +7,9 @@ const app = Vue.createApp({ LvPopup } }); + +FhcApps.makeExtendable(app); + app .use(PluginsPhrasen) .mount('#wrapper'); \ No newline at end of file From d294d17e375add1c2d89bef9ee59a7890c681cd3 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 9 Oct 2025 10:42:22 +0200 Subject: [PATCH 12/40] use fhcApps for lehre/lvplanung/LvTemplates --- application/views/lehre/lvplanung/lvTemplateUebersicht.php | 2 +- public/js/apps/lehre/lvplanung/LvTemplates.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/application/views/lehre/lvplanung/lvTemplateUebersicht.php b/application/views/lehre/lvplanung/lvTemplateUebersicht.php index 5c873486c..1d5a2e777 100644 --- a/application/views/lehre/lvplanung/lvTemplateUebersicht.php +++ b/application/views/lehre/lvplanung/lvTemplateUebersicht.php @@ -9,7 +9,7 @@ $includesArray = array( 'primevue3' => true, 'navigationcomponent' => true, 'filtercomponent' => true, - 'customJSModules' => array('public/js/apps/lehre/lvplanung/LvTemplates.js'), + 'fhcApps' => array('lehre/lvplanung/LvTemplates'), 'customCSSs' => array( 'public/css/Fhc.css', 'public/css/lvTemplateUebersicht.css' diff --git a/public/js/apps/lehre/lvplanung/LvTemplates.js b/public/js/apps/lehre/lvplanung/LvTemplates.js index 655d611ce..b19b1f730 100644 --- a/public/js/apps/lehre/lvplanung/LvTemplates.js +++ b/public/js/apps/lehre/lvplanung/LvTemplates.js @@ -28,6 +28,8 @@ const lvTemplatesApp = Vue.createApp({ } }); +FhcApps.makeExtendable(lvTemplatesApp); + lvTemplatesApp .use(primevue.config.default,{zIndex: {overlay: 9999}}) .use(PluginsPhrasen) From 70c230edcee856a9386f59e97ee136032e1bfae8 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 9 Oct 2025 10:44:13 +0200 Subject: [PATCH 13/40] use fhcApps for LogsViewer/LogsViewer --- application/views/system/logs/logsViewer.php | 2 +- public/js/apps/LogsViewer/LogsViewer.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/application/views/system/logs/logsViewer.php b/application/views/system/logs/logsViewer.php index ddfe855fe..60d9075d0 100644 --- a/application/views/system/logs/logsViewer.php +++ b/application/views/system/logs/logsViewer.php @@ -13,7 +13,7 @@ 'global' => array('mailAnXversandt'), 'ui' => array('bitteEintragWaehlen') ), - 'customJSModules' => array('public/js/apps/LogsViewer/LogsViewer.js'), + 'fhcApps' => array('LogsViewer/LogsViewer'), ); $this->load->view('templates/FHC-Header', $includesArray); diff --git a/public/js/apps/LogsViewer/LogsViewer.js b/public/js/apps/LogsViewer/LogsViewer.js index eeb4b38a7..ad377a369 100644 --- a/public/js/apps/LogsViewer/LogsViewer.js +++ b/public/js/apps/LogsViewer/LogsViewer.js @@ -42,5 +42,7 @@ const logsViewerApp = Vue.createApp({ } }); +FhcApps.makeExtendable(logsViewerApp); + logsViewerApp.use(PluginsPhrasen).mount('#main'); From 601c4367dccad16d497940aede1d358a471f14a6 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Thu, 9 Oct 2025 10:57:51 +0200 Subject: [PATCH 14/40] use fhcApps for CIS --- application/views/templates/CISVUE-Footer.php | 6 +++--- application/views/templates/CISVUE-Header.php | 6 +++--- public/js/apps/Cis.js | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/application/views/templates/CISVUE-Footer.php b/application/views/templates/CISVUE-Footer.php index d7c1de24c..48943650d 100644 --- a/application/views/templates/CISVUE-Footer.php +++ b/application/views/templates/CISVUE-Footer.php @@ -5,9 +5,9 @@ $includesArray = array( 'bootstrap5' => true, 'fontawesome6' => true, 'axios027' => true, - 'customJSModules' => array_merge([ - 'public/js/apps/Cis.js' - ], $customJSModules ?? []), + 'fhcApps' => array_merge([ + 'Cis' + ], $fhcApps ?? []), 'customCSSs' => array_merge([ 'public/css/Cis4/Cis.css' ], $customCSSs ?? []) diff --git a/application/views/templates/CISVUE-Header.php b/application/views/templates/CISVUE-Header.php index 358fc75c9..943d26d80 100644 --- a/application/views/templates/CISVUE-Header.php +++ b/application/views/templates/CISVUE-Header.php @@ -7,9 +7,9 @@ $includesArray = array( 'fontawesome6' => true, 'axios027' => true, 'primevue3' => true, - 'customJSModules' => array_merge([ - 'public/js/apps/Cis.js' - ], $customJSModules ?? []), + 'fhcApps' => array_merge([ + 'Cis' + ], $fhcApps ?? []), 'customCSSs' => array_merge([ 'public/css/Cis4/Cis.css', $this->config->item('theme_css'), diff --git a/public/js/apps/Cis.js b/public/js/apps/Cis.js index 5b76c5721..c88a47a35 100644 --- a/public/js/apps/Cis.js +++ b/public/js/apps/Cis.js @@ -142,6 +142,9 @@ const app = Vue.createApp({ } } }); + +FhcApps.makeExtendable(app); + app.use(primevue.config.default, { zIndex: { overlay: 9000, From 0b6dc342207c4a908d7bedb68f9e75a8d8f723fc Mon Sep 17 00:00:00 2001 From: Paolo Date: Mon, 10 Nov 2025 15:41:01 +0100 Subject: [PATCH 15/40] If docsbox queue is slow, the DocsboxLib can stop checking the queued document status and raise an error --- application/libraries/DocsboxLib.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/application/libraries/DocsboxLib.php b/application/libraries/DocsboxLib.php index f9167c379..31169d579 100644 --- a/application/libraries/DocsboxLib.php +++ b/application/libraries/DocsboxLib.php @@ -157,6 +157,8 @@ class DocsboxLib ->expectsJson() ->send(); + error_log(print_r($getStatusResponse, 1)); + // Checks that: // - the response is not empty // - the reponse body has the property id @@ -180,7 +182,8 @@ class DocsboxLib } // Just started or still working on it elseif ($getStatusResponse->body->status == self::STATUS_WORKING - || $getStatusResponse->body->status == self::STATUS_STARTED) + || $getStatusResponse->body->status == self::STATUS_STARTED + || $getStatusResponse->body->status == self::STATUS_QUEUED) { // go on! } From 1ce362b66bf353abc18b66662c48dd3a778a8c6e Mon Sep 17 00:00:00 2001 From: Paolo Date: Wed, 7 Jan 2026 15:54:59 +0100 Subject: [PATCH 16/40] Removed forgotten error_log --- application/libraries/DocsboxLib.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/application/libraries/DocsboxLib.php b/application/libraries/DocsboxLib.php index 31169d579..184855ad8 100644 --- a/application/libraries/DocsboxLib.php +++ b/application/libraries/DocsboxLib.php @@ -157,8 +157,6 @@ class DocsboxLib ->expectsJson() ->send(); - error_log(print_r($getStatusResponse, 1)); - // Checks that: // - the response is not empty // - the reponse body has the property id From fa7a1257278e89f3d0d5ef49e6e80ff3c2c6ecdf Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Wed, 18 Feb 2026 21:18:57 +0100 Subject: [PATCH 17/40] Studierendenverwaltung archivieren: error message when no studentlehrverband found --- .../controllers/api/frontend/v1/Documents.php | 4 ++- .../controllers/jobs/PlausiIssueProducer.php | 4 +++ system/phrasesupdate.php | 30 ++++++++++++++++--- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/application/controllers/api/frontend/v1/Documents.php b/application/controllers/api/frontend/v1/Documents.php index 7b2fc4a15..dcc0bb9ac 100644 --- a/application/controllers/api/frontend/v1/Documents.php +++ b/application/controllers/api/frontend/v1/Documents.php @@ -208,7 +208,6 @@ class Documents extends FHCAPI_Controller $this->load->model('system/Vorlage_model', 'VorlageModel'); $result = $this->VorlageModel->load($xsl); - $this->addMeta("ress", $result); $vorlage = current($this->getDataOrTerminateWithError($result)); if (!$vorlage) show_404(); @@ -251,6 +250,9 @@ class Documents extends FHCAPI_Controller 'studiensemester_kurzbz' => $ss, 'student_uid' => $akteData['uid'] ]); + + if (!hasData($result)) $this->terminateWithError($this->p->t("stv", "error_noLehrverbandAssigned")); + $res = current($this->getDataOrTerminateWithError($result)); $studiengang_kz = $res->studiengang_kz; diff --git a/application/controllers/jobs/PlausiIssueProducer.php b/application/controllers/jobs/PlausiIssueProducer.php index b667e835d..0aaecf5f5 100644 --- a/application/controllers/jobs/PlausiIssueProducer.php +++ b/application/controllers/jobs/PlausiIssueProducer.php @@ -33,6 +33,10 @@ class PlausiIssueProducer extends PlausiIssueProducer_Controller */ public function run($studiensemester_kurzbz = null, $studiengang_kz = null) { + //$a = $this->StudiensemesterModel->getByDate('2026-02-14', '2026-02-16'); + $a = $this->StudiensemesterModel->getAktOrNextSemester(); + var_dump(getData($a)); + die(); // get Studiensemester if (isEmptyString($studiensemester_kurzbz)) $studiensemester_kurzbz = $this->_currentStudiensemester; diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 5dc9bc1c0..efe300955 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -44644,9 +44644,9 @@ array( 'phrases' => array( array( 'sprache' => 'German', - 'text' => "Für den gesamten Studiengang verbindlicher Termin. - - Liegt ein Termin in der Vergangenheit, kann nichts mehr hochgeladen werden. Ist es dennoch erforderlich, + 'text' => "Für den gesamten Studiengang verbindlicher Termin. + + Liegt ein Termin in der Vergangenheit, kann nichts mehr hochgeladen werden. Ist es dennoch erforderlich, haben Studierende bei der Studiengangsassistenz um eine Korrektur dieses Termins anzusuchen.", 'description' => '', 'insertvon' => 'system' @@ -44837,7 +44837,7 @@ array( array( 'sprache' => 'German', 'text' => "Verspätete Projektabgabe ist bei Terminen, welche von der Studiengangsassistenz für den gesamten Studiengang fixiert wurden nicht erlaubt! - + Um einen Endupload durchführen zu können, müssen Sie ein positiv benotetes Quality Gate 1 & Quality Gate 2 in der relevanten Projektarbeit absolviert haben.", 'description' => '', 'insertvon' => 'system' @@ -55923,6 +55923,28 @@ I have been informed that I am under no obligation to consent to the transmissio ) ), // ### Refactor Messages END + // + array( + 'app' => 'core', + 'category' => 'stv', + 'phrase' => 'error_noLehrverbandAssigned', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'StudentIn ist in diesem Semester keinem Lehrverband zugeteilt', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Student has no assignment to any teaching association', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + ); From f068b56083b81ef18195a636fb7ce21df8dedb65 Mon Sep 17 00:00:00 2001 From: Alexei Karpenko Date: Wed, 18 Feb 2026 22:30:29 +0100 Subject: [PATCH 18/40] PlausiIssueProducer: removed debugging output and die --- application/controllers/jobs/PlausiIssueProducer.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/application/controllers/jobs/PlausiIssueProducer.php b/application/controllers/jobs/PlausiIssueProducer.php index 0aaecf5f5..b667e835d 100644 --- a/application/controllers/jobs/PlausiIssueProducer.php +++ b/application/controllers/jobs/PlausiIssueProducer.php @@ -33,10 +33,6 @@ class PlausiIssueProducer extends PlausiIssueProducer_Controller */ public function run($studiensemester_kurzbz = null, $studiengang_kz = null) { - //$a = $this->StudiensemesterModel->getByDate('2026-02-14', '2026-02-16'); - $a = $this->StudiensemesterModel->getAktOrNextSemester(); - var_dump(getData($a)); - die(); // get Studiensemester if (isEmptyString($studiensemester_kurzbz)) $studiensemester_kurzbz = $this->_currentStudiensemester; From f3986688f231ec97e619208cd0e619a13a4ceb7a Mon Sep 17 00:00:00 2001 From: ma0048 Date: Thu, 26 Feb 2026 12:50:37 +0100 Subject: [PATCH 19/40] selfoverview: nur aktive kategorien anzeigen uebersetzungen hinzugefuegt --- system/phrasesupdate.php | 166 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index deb856663..f7fe822ce 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -3863,6 +3863,172 @@ $phrases = array( ) ) ), + array( + 'app' => 'pep', + 'category' => 'ui', + 'phrase' => 'geplZeitraum', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'geplanter Zeitraum', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'planned Period', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'pep', + 'category' => 'ui', + 'phrase' => 'bitteAuswaehlen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Bitte auswählen...', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Please select...', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'pep', + 'category' => 'ui', + 'phrase' => 'hinweisLehrende', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Hinweis für Lehrende', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Note for Lecturers', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'pep', + 'category' => 'ui', + 'phrase' => 'lehreinheiten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Lehreinheiten', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Teaching Units', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'pep', + 'category' => 'ui', + 'phrase' => 'lead', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Leitung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Lead', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'pep', + 'category' => 'ui', + 'phrase' => 'teamlead', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Team / Leitung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Team / Lead', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'pep', + 'category' => 'ui', + 'phrase' => 'ausblick_lvplanung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Ausblick auf Ihre mögliche LV-Planung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Preview of Your Potential Course Planning', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + + array( + 'app' => 'pep', + 'category' => 'ui', + 'phrase' => 'detailselfoverview', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Achtung: die vorliegenden Informationen stellen eine Vorabplanung dar und sind als Anfrage an Sie gedacht.

+ Die Beauftragung der tatsächlichen Lehrveranstaltungen erfolgt durch Ihre Kompetenzfeldleitung.

+ Ihre aktuell gültigen Lehraufträge und den LV Plan des aktuellen Semesters (Termine) finden Sie wie gewohnt unter „mein CIS“ -> „LV-Plan Hauptmenü“ bzw. „Lehrauftragsverwaltung“.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Please note: The information provided represents a preliminary planning and is intended as an inquiry to you.

+ The official assignment of the actual courses will be carried out by your Competence Field Manager.

+ Your currently valid teaching assignments and the course schedule for the current semester (dates) can be found as usual under “My CIS” → “Schedule Main Menu” or “Teaching Assignment Administration”', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( 'app' => 'pep', 'category' => 'ui', From 26fca87c75ff5d4caa57754192d76c32c60099ae Mon Sep 17 00:00:00 2001 From: Harald Bamberger Date: Thu, 26 Feb 2026 14:56:33 +0100 Subject: [PATCH 20/40] refactor VueJs App magic into a helper function --- application/helpers/hlp_header_helper.php | 78 +++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/application/helpers/hlp_header_helper.php b/application/helpers/hlp_header_helper.php index 24c02eac5..86c7dae63 100644 --- a/application/helpers/hlp_header_helper.php +++ b/application/helpers/hlp_header_helper.php @@ -246,3 +246,81 @@ function generateSkipLink($skipID) $toPrint.='" class="fhcSkipLink" aria-label="Skip to main content">'; echo $toPrint; } + +/* + * Manipulate CI views includes Array to load + * - public/js/FhcApps.js via customJSs and + * - app customisation js and/or css from extensions via customJSModules + * if customJSModules contains at least one vuejs app and customisation files + * exist in extensions + */ +function extendableApps($includes) +{ + $start = microtime(true); + if(!isset($includes['customJSModules'])) + { + return; + } + + if(!is_array($includes['customJSModules'])) + { + $includes['customJSModules'] = array($includes['customJSModules']); + } + + $extensions = array(); + $fsiterator = new FilesystemIterator(FHCPATH . 'application/extensions'); + foreach ($fsiterator as $fsitem) + { + if(preg_match('/^FHC-Core-/', $fsitem->getBasename())) + { + $extensions[] = $fsitem->getBasename(); + } + } + + $appscount = 0; + foreach($includes['customJSModules'] as $item) + { + $matches = array(); + if(preg_match('#^public/(extensions/FHC-Core-.+)?js/apps/(.*)\.js$#', $item, $matches)) + { + $appscount++; + + $fhcextension = $matches[1]; + $app = $matches[2]; + + $extend_js_suffix = 'js/extend_app/' . $fhcextension . $app . '.js'; + $extend_css_suffix = 'css/extend_app/' . $fhcextension . $app . '.css'; + + foreach($extensions as $extension) + { + $extend_js = 'public/extensions/' . $extension . '/' . $extend_js_suffix; + $extend_css = 'public/extensions/' . $extension . '/' . $extend_css_suffix; + + if(is_readable(FHCPATH . $extend_js)) + { + array_push($includes['customJSModules'], $extend_js); + } + + if(is_readable(FHCPATH . $extend_css)) + { + array_push($includes['customCSSs'], $extend_css); + } + } + } + } + + if($appscount > 0) + { + if(!isset($includes['customJSs'])) + { + $includes['customJSs'] = array(); + } + elseif(!is_array($includes['customJSs'])) + { + $includes['customJSs'] = array($includes['customJSs']); + } + array_push($includes['customJSs'], 'public/js/FhcApps.js'); + } + + return $includes; +} From 1ae072390edf23a0bb32fdeeedfee30e370922c6 Mon Sep 17 00:00:00 2001 From: Harald Bamberger Date: Thu, 26 Feb 2026 15:27:52 +0100 Subject: [PATCH 21/40] revert changes to add fhcApps property, not using path based syntax, to CI views include array --- application/views/Cis/Documents.php | 6 +- application/views/Cis/ProfilUpdate.php | 8 +-- .../views/CisRouterView/CisRouterView.php | 4 +- application/views/LVVerwaltung.php | 8 +-- application/views/Studentenverwaltung.php | 8 +-- application/views/codex/bismeldestichtag.php | 6 +- application/views/lehre/Antrag/Create.php | 6 +- .../views/lehre/Antrag/Leitung/List.php | 6 +- .../views/lehre/Antrag/Student/List.php | 6 +- .../lehre/Antrag/Wiederholung/Student.php | 6 +- .../lehre/lvplanung/lvTemplateUebersicht.php | 6 +- application/views/system/logs/logsViewer.php | 6 +- application/views/templates/CISVUE-Footer.php | 6 +- application/views/templates/CISVUE-Header.php | 6 +- application/views/templates/FHC-Common.php | 57 ------------------- 15 files changed, 44 insertions(+), 101 deletions(-) diff --git a/application/views/Cis/Documents.php b/application/views/Cis/Documents.php index fa491fa11..fcafff57c 100644 --- a/application/views/Cis/Documents.php +++ b/application/views/Cis/Documents.php @@ -1,9 +1,9 @@ 'Documents', 'tabulator5' => true, - 'fhcApps' => ['Cis/Documents'] -); + 'customJSModules' => ['public/js/apps/Cis/Documents.js'] +)); $this->load->view('templates/CISVUE-Header', $includesArray); ?> diff --git a/application/views/Cis/ProfilUpdate.php b/application/views/Cis/ProfilUpdate.php index 525d261a7..2295a753f 100644 --- a/application/views/Cis/ProfilUpdate.php +++ b/application/views/Cis/ProfilUpdate.php @@ -1,18 +1,18 @@ 'Profil Änderungen', 'vue3' => true, 'bootstrap5' => true, 'fontawesome6'=> true, 'axios027' => true, 'tabulator5' => true, - 'fhcApps' => array( - 'Cis/ProfilUpdateRequests' + 'customJSModules' => array( + 'public/js/apps/Cis/ProfilUpdateRequests.js' ), 'customCSSs' => array( 'public/css/components/FilterComponent.css','public/css/components/FormUnderline.css' ) -); +)); if(defined("CIS4")) { diff --git a/application/views/CisRouterView/CisRouterView.php b/application/views/CisRouterView/CisRouterView.php index ab22fbb81..42e49e38b 100644 --- a/application/views/CisRouterView/CisRouterView.php +++ b/application/views/CisRouterView/CisRouterView.php @@ -1,6 +1,6 @@ 'Cis4', 'axios027' => true, 'bootstrap5' => true, @@ -36,7 +36,7 @@ $includesArray = array( 'public/js/apps/Dashboard/Fhc.js' ), -); +)); $this->load->view('templates/CISVUE-Header', $includesArray); ?> diff --git a/application/views/LVVerwaltung.php b/application/views/LVVerwaltung.php index 5c4c9549e..d2856ad3e 100644 --- a/application/views/LVVerwaltung.php +++ b/application/views/LVVerwaltung.php @@ -1,5 +1,5 @@ 'LVVerwaltung', 'axios027' => true, 'bootstrap5' => true, @@ -17,10 +17,10 @@ 'public/css/Lvverwaltung.css' ], - 'fhcApps' => [ - 'LVVerwaltung' + 'customJSModules' => [ + 'public/js/apps/LVVerwaltung.js' ] - ); + )); $this->load->view('templates/FHC-Header', $includesArray); diff --git a/application/views/Studentenverwaltung.php b/application/views/Studentenverwaltung.php index aa4891e9a..fb0913806 100644 --- a/application/views/Studentenverwaltung.php +++ b/application/views/Studentenverwaltung.php @@ -1,5 +1,5 @@ 'Studentenverwaltung', 'axios027' => true, 'bootstrap5' => true, @@ -26,10 +26,10 @@ #'vendor/npm-asset/primevue/tree/tree.min.js', #'vendor/npm-asset/primevue/toast/toast.min.js' ], - 'fhcApps' => [ - 'Studentenverwaltung' + 'customJSModules' => [ + 'public/js/apps/Studentenverwaltung.js' ] - ); + )); $this->load->view('templates/FHC-Header', $includesArray); ?> diff --git a/application/views/codex/bismeldestichtag.php b/application/views/codex/bismeldestichtag.php index 2f024d25e..fc0311674 100644 --- a/application/views/codex/bismeldestichtag.php +++ b/application/views/codex/bismeldestichtag.php @@ -1,5 +1,5 @@ 'Bismeldestichtage', 'axios027' => true, 'bootstrap5' => true, @@ -10,8 +10,8 @@ 'tabulator5' => true, 'customCSSs' => array('vendor/vuejs/vuedatepicker_css/main.css'), 'customJSs' => array('vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js'), - 'fhcApps' => array('Bismeldestichtag/Bismeldestichtag') - ); + 'customJSModules' => array('public/js/apps/Bismeldestichtag/Bismeldestichtag.js') + )); $this->load->view('templates/FHC-Header', $includesArray); ?> diff --git a/application/views/lehre/Antrag/Create.php b/application/views/lehre/Antrag/Create.php index 36a39078f..56d1e0a28 100644 --- a/application/views/lehre/Antrag/Create.php +++ b/application/views/lehre/Antrag/Create.php @@ -1,5 +1,5 @@ 'Antrag auf Änderung des Studierendenstatus', 'cis' => true, 'vue3' => true, @@ -8,7 +8,7 @@ $sitesettings = array( 'fontawesome6' => true, 'phrases' => array( ), - 'fhcApps' => array('lehre/Antrag'), + 'customJSModules' => array('public/js/apps/lehre/Antrag.js'), 'customCSSs' => array( 'public/css/Fhc.css', 'public/css/components/primevue.css', @@ -16,7 +16,7 @@ $sitesettings = array( ), 'customJSs' => array( ) -); +)); if(defined('CIS4')){ $this->load->view( diff --git a/application/views/lehre/Antrag/Leitung/List.php b/application/views/lehre/Antrag/Leitung/List.php index b1ba44a4c..f6c95bc86 100644 --- a/application/views/lehre/Antrag/Leitung/List.php +++ b/application/views/lehre/Antrag/Leitung/List.php @@ -2,7 +2,7 @@ use \DateTime as DateTime; -$sitesettings = array( +$sitesettings = extendableApps(array( 'title' => 'Anträge auf Änderung des Studierendenstatus', 'cis' => true, 'vue3' => true, @@ -18,14 +18,14 @@ $sitesettings = array( 'lehre', 'person', ), - 'fhcApps' => array('lehre/Antrag/Leitung'), + 'customJSModules' => array('public/js/apps/lehre/Antrag/Leitung.js'), 'customCSSs' => array( 'public/css/Fhc.css', 'public/css/components/primevue.css', ), 'customJSs' => array( ) -); +)); $this->load->view( 'templates/FHC-Header', diff --git a/application/views/lehre/Antrag/Student/List.php b/application/views/lehre/Antrag/Student/List.php index 9454e2006..1b467e576 100644 --- a/application/views/lehre/Antrag/Student/List.php +++ b/application/views/lehre/Antrag/Student/List.php @@ -1,5 +1,5 @@ 'Antrag auf Änderung des Studierendenstatus', 'cis' => true, 'vue3' => true, @@ -8,14 +8,14 @@ $sitesettings = array( 'fontawesome6' => true, 'phrases' => array( ), - 'fhcApps' => array('lehre/Antrag/Student'), + 'customJSModules' => array('public/js/apps/lehre/Antrag/Student.js'), 'customCSSs' => array( 'public/css/Fhc.css', 'public/css/components/primevue.css', ), 'customJSs' => array( ) -); +)); if(defined('CIS4')){ $this->load->view( diff --git a/application/views/lehre/Antrag/Wiederholung/Student.php b/application/views/lehre/Antrag/Wiederholung/Student.php index 73405fc0a..65707cc7b 100644 --- a/application/views/lehre/Antrag/Wiederholung/Student.php +++ b/application/views/lehre/Antrag/Wiederholung/Student.php @@ -1,5 +1,5 @@ 'Antrag Wiederholung vom Studium', 'cis' => true, 'vue3' => true, @@ -12,14 +12,14 @@ $sitesettings = array( 'lehre', 'global' ), - 'fhcApps' => array('lehre/Antrag/Lvzuweisung'), + 'customJSModules' => array('public/js/apps/lehre/Antrag/Lvzuweisung.js'), 'customCSSs' => array( 'public/css/Fhc.css', 'public/css/components/primevue.css', ), 'customJSs' => array( ) -); +)); $this->load->view( 'templates/FHC-Header', diff --git a/application/views/lehre/lvplanung/lvTemplateUebersicht.php b/application/views/lehre/lvplanung/lvTemplateUebersicht.php index 1d5a2e777..8e47677f0 100644 --- a/application/views/lehre/lvplanung/lvTemplateUebersicht.php +++ b/application/views/lehre/lvplanung/lvTemplateUebersicht.php @@ -1,5 +1,5 @@ 'LV Template Übersicht', 'vue3' => true, 'axios027' => true, @@ -9,12 +9,12 @@ $includesArray = array( 'primevue3' => true, 'navigationcomponent' => true, 'filtercomponent' => true, - 'fhcApps' => array('lehre/lvplanung/LvTemplates'), + 'customJSModules' => array('public/js/apps/lehre/lvplanung/LvTemplates.js'), 'customCSSs' => array( 'public/css/Fhc.css', 'public/css/lvTemplateUebersicht.css' ) -); +)); $this->load->view('templates/FHC-Header', $includesArray); ?> diff --git a/application/views/system/logs/logsViewer.php b/application/views/system/logs/logsViewer.php index 60d9075d0..1d6b50394 100644 --- a/application/views/system/logs/logsViewer.php +++ b/application/views/system/logs/logsViewer.php @@ -1,5 +1,5 @@ 'Logs Viewer', 'axios027' => true, 'bootstrap5' => true, @@ -13,8 +13,8 @@ 'global' => array('mailAnXversandt'), 'ui' => array('bitteEintragWaehlen') ), - 'fhcApps' => array('LogsViewer/LogsViewer'), - ); + 'customJSModules' => array('public/js/apps/LogsViewer/LogsViewer.js'), + )); $this->load->view('templates/FHC-Header', $includesArray); ?> diff --git a/application/views/templates/CISVUE-Footer.php b/application/views/templates/CISVUE-Footer.php index 48943650d..d7c1de24c 100644 --- a/application/views/templates/CISVUE-Footer.php +++ b/application/views/templates/CISVUE-Footer.php @@ -5,9 +5,9 @@ $includesArray = array( 'bootstrap5' => true, 'fontawesome6' => true, 'axios027' => true, - 'fhcApps' => array_merge([ - 'Cis' - ], $fhcApps ?? []), + 'customJSModules' => array_merge([ + 'public/js/apps/Cis.js' + ], $customJSModules ?? []), 'customCSSs' => array_merge([ 'public/css/Cis4/Cis.css' ], $customCSSs ?? []) diff --git a/application/views/templates/CISVUE-Header.php b/application/views/templates/CISVUE-Header.php index 943d26d80..358fc75c9 100644 --- a/application/views/templates/CISVUE-Header.php +++ b/application/views/templates/CISVUE-Header.php @@ -7,9 +7,9 @@ $includesArray = array( 'fontawesome6' => true, 'axios027' => true, 'primevue3' => true, - 'fhcApps' => array_merge([ - 'Cis' - ], $fhcApps ?? []), + 'customJSModules' => array_merge([ + 'public/js/apps/Cis.js' + ], $customJSModules ?? []), 'customCSSs' => array_merge([ 'public/css/Cis4/Cis.css', $this->config->item('theme_css'), diff --git a/application/views/templates/FHC-Common.php b/application/views/templates/FHC-Common.php index 955583500..71f9c46c4 100644 --- a/application/views/templates/FHC-Common.php +++ b/application/views/templates/FHC-Common.php @@ -48,60 +48,3 @@ $udfs = isset($udfs) ? $udfs : false; $widgets = isset($widgets) ? $widgets : false; $tags = isset($tags) ? $tags : false; - -// VueJs App magic -if (isset($fhcApps)) { - if (!isset($customJSs)) - $customJSs = ['public/js/FhcApps.js']; - elseif (!is_array($customJSs)) - $customJSs = [$customJSs, 'public/js/FhcApps.js']; - else - array_push($customJSs, 'public/js/FhcApps.js'); - - if (!isset($customJSModules)) - $customJSModules = []; - elseif (!is_array($customJSModules)) - $customJSModules = [$customJSModules]; - - if (!isset($customCSSs)) - $customCSSs = []; - elseif (!is_array($customCSSs)) - $customCSSs = [$customCSSs]; - - $ext_path = 'public/extensions/'; - $ext_realpath = str_replace('/', DIRECTORY_SEPARATOR, $ext_path); - - foreach ($fhcApps as $app) { - if (!strstr($app, ':')) { - $app_js_path = 'public/js/apps/' . $app . '.js'; - $app_css_path = 'public/css/apps/' . $app . '.css'; - $app_js_ext_path = '/js/extend_app/' . $app . '.js'; - $app_css_ext_path = '/css/extend_app/' . $app . '.css'; - } else { - list($ext_name, $app_path) = explode(':', $app); - $app_js_path = 'public/extensions/' . $ext_name . '/js/apps/' . $app_path . '.js'; - $app_css_path = 'public/extensions/' . $ext_name . '/css/apps/' . $app_path . '.css'; - $app_js_ext_path = '/js/extend_app/extensions/' . $ext_name . '/' . $app_path . '.js'; - $app_css_ext_path = '/css/extend_app/extensions/' . $ext_name . '/' . $app_path . '.css'; - } - - if (file_exists(FHCPATH . str_replace('/', DIRECTORY_SEPARATOR, $app_css_path))) - array_push($customCSSs, $app_css_path); - - foreach (scandir(FHCPATH . $ext_realpath) as $extension_name) { - if ($extension_name[0] == '.') - continue; - - $app_js_ext_realpath = str_replace('/', DIRECTORY_SEPARATOR, $app_js_ext_path); - if (file_exists(FHCPATH . $ext_realpath . $extension_name . $app_js_ext_realpath)) { - array_push($customJSModules, $ext_path . $extension_name . $app_js_ext_path); - } - $app_css_ext_realpath = str_replace('/', DIRECTORY_SEPARATOR, $app_css_ext_path); - if (file_exists(FHCPATH . $ext_realpath . $extension_name . $app_css_ext_realpath)) { - array_push($customCSSs, $ext_path . $extension_name . $app_css_ext_path); - } - } - - array_push($customJSModules, $app_js_path); - } -} From 4deed45f298bf95952a5aa957cfc0a032699d474 Mon Sep 17 00:00:00 2001 From: Harald Bamberger Date: Thu, 26 Feb 2026 15:53:41 +0100 Subject: [PATCH 22/40] prepend extend_app js to customJSModules array, use FhcApps in Dashboard/Fhc App --- application/helpers/hlp_header_helper.php | 2 +- public/js/apps/Dashboard/Fhc.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/application/helpers/hlp_header_helper.php b/application/helpers/hlp_header_helper.php index 86c7dae63..2d425500d 100644 --- a/application/helpers/hlp_header_helper.php +++ b/application/helpers/hlp_header_helper.php @@ -298,7 +298,7 @@ function extendableApps($includes) if(is_readable(FHCPATH . $extend_js)) { - array_push($includes['customJSModules'], $extend_js); + array_unshift($includes['customJSModules'], $extend_js); } if(is_readable(FHCPATH . $extend_css)) diff --git a/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js index 093ad815b..3dd2f3fc7 100644 --- a/public/js/apps/Dashboard/Fhc.js +++ b/public/js/apps/Dashboard/Fhc.js @@ -321,6 +321,9 @@ const app = Vue.createApp({ // kind of a bandaid for bad css on some pages to avoid horizontal scroll setScrollbarWidth(); +FhcApps.router.makeExtendable(router); +FhcApps.makeExtendable(app); + app.use(router); app.use(primevue.config.default, { zIndex: { From 43a37021a5eafedca620b9a791cecc29da931483 Mon Sep 17 00:00:00 2001 From: Harald Bamberger Date: Fri, 27 Feb 2026 09:24:47 +0100 Subject: [PATCH 23/40] ensure extend_app js files from extensions are loaded directly before the apps js file --- application/helpers/hlp_header_helper.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/application/helpers/hlp_header_helper.php b/application/helpers/hlp_header_helper.php index 9c085f6cb..68ab2c23f 100644 --- a/application/helpers/hlp_header_helper.php +++ b/application/helpers/hlp_header_helper.php @@ -279,7 +279,6 @@ function absoluteJsImportUrl($relurl) */ function extendableApps($includes) { - $start = microtime(true); if(!isset($includes['customJSModules'])) { return; @@ -301,6 +300,7 @@ function extendableApps($includes) } $appscount = 0; + $tmpCustomJSModules = array(); foreach($includes['customJSModules'] as $item) { $matches = array(); @@ -321,7 +321,7 @@ function extendableApps($includes) if(is_readable(FHCPATH . $extend_js)) { - array_unshift($includes['customJSModules'], $extend_js); + array_push($tmpCustomJSModules, $extend_js); } if(is_readable(FHCPATH . $extend_css)) @@ -330,7 +330,9 @@ function extendableApps($includes) } } } + array_push($tmpCustomJSModules, $item); } + $includes['customJSModules'] = $tmpCustomJSModules; if($appscount > 0) { From 28f4a38752da069eac5bb212f0db1849a8838217 Mon Sep 17 00:00:00 2001 From: Harald Bamberger Date: Fri, 27 Feb 2026 16:50:50 +0100 Subject: [PATCH 24/40] refactor helper function extendableApps to singleton helper class ExtendableAppsHelper and use it in FHC-Header and FHC-Footer, revert previous changes to other CI views --- application/helpers/hlp_header_helper.php | 206 ++++++++++++++---- application/views/Cis/Documents.php | 4 +- application/views/Cis/ProfilUpdate.php | 4 +- .../views/CisRouterView/CisRouterView.php | 4 +- application/views/LVVerwaltung.php | 4 +- application/views/Studentenverwaltung.php | 4 +- application/views/codex/bismeldestichtag.php | 4 +- application/views/lehre/Antrag/Create.php | 4 +- .../views/lehre/Antrag/Leitung/List.php | 4 +- .../views/lehre/Antrag/Student/List.php | 4 +- .../lehre/Antrag/Wiederholung/Student.php | 4 +- .../lehre/lvplanung/lvTemplateUebersicht.php | 4 +- application/views/system/logs/logsViewer.php | 4 +- application/views/templates/FHC-Footer.php | 10 +- application/views/templates/FHC-Header.php | 7 +- 15 files changed, 197 insertions(+), 74 deletions(-) diff --git a/application/helpers/hlp_header_helper.php b/application/helpers/hlp_header_helper.php index 68ab2c23f..27dfba5a1 100644 --- a/application/helpers/hlp_header_helper.php +++ b/application/helpers/hlp_header_helper.php @@ -277,75 +277,191 @@ function absoluteJsImportUrl($relurl) * if customJSModules contains at least one vuejs app and customisation files * exist in extensions */ -function extendableApps($includes) +class ExtendableAppsHelper { - if(!isset($includes['customJSModules'])) + private static $instance = null; + + protected $extensions; + + protected $customCSSs; + protected $customJSs; + protected $customJSModules; + + protected $initialised; + protected $appscount; + + protected $extCustomCSSs; + protected $extCustomJSs; + protected $extCustomJSModules; + + private function __construct() { - return; + $this->extensions = array(); + $this->customCSSs = null; + $this->customJSs = null; + $this->customJSModules = null; + + $this->initialised = false; + $this->appscount = 0; + + $this->extCustomCSSs = null; + $this->extCustomJSs = null; + $this->extCustomJSModules = null; } - if(!is_array($includes['customJSModules'])) + public static function getInstance() { - $includes['customJSModules'] = array($includes['customJSModules']); - } - - $extensions = array(); - $fsiterator = new FilesystemIterator(FHCPATH . 'application/extensions'); - foreach ($fsiterator as $fsitem) - { - if(preg_match('/^FHC-Core-/', $fsitem->getBasename())) + if(self::$instance === null) { - $extensions[] = $fsitem->getBasename(); + self::$instance = new ExtendableAppsHelper(); } + return self::$instance; } - $appscount = 0; - $tmpCustomJSModules = array(); - foreach($includes['customJSModules'] as $item) + public function init($customCSSs, $customJSs, $customJSModules) { - $matches = array(); - if(preg_match('#^public/(extensions/FHC-Core-.+)?js/apps/(.*)\.js$#', $item, $matches)) + if($this->initialised) { - $appscount++; + return; + } - $fhcextension = $matches[1]; - $app = $matches[2]; + $this->customCSSs = $customCSSs; + $this->customJSs = $customJSs; + $this->customJSModules = $customJSModules; + $this->initialised = true; - $extend_js_suffix = 'js/extend_app/' . $fhcextension . $app . '.js'; - $extend_css_suffix = 'css/extend_app/' . $fhcextension . $app . '.css'; + if(!isset($this->customJSModules)) + { + return; + } - foreach($extensions as $extension) + if(!is_array($this->customJSModules)) + { + $this->customJSModules = array($this->customJSModules); + } + + if(count($this->customJSModules) < 1) + { + return; + } + + $this->buildExtensionsList(); + $this->prepareExtendedArrays(); + } + + public function getCustomCSSs() + { + if(is_null($this->extCustomCSSs)) + { + return $this->customCSSs; + } + return $this->extCustomCSSs; + } + + public function getCustomJSs() + { + if(is_null($this->extCustomJSs)) + { + return $this->customJSs; + } + return $this->extCustomJSs; + } + + public function getCustomJSModules() + { + if(is_null($this->extCustomJSModules)) + { + return $this->customJSModules; + } + return $this->extCustomJSModules; + } + + protected function buildExtensionsList() + { + $this->extensions = array(); + $fsiterator = new FilesystemIterator(FHCPATH . 'application/extensions'); + foreach ($fsiterator as $fsitem) + { + if(preg_match('/^FHC-Core-/', $fsitem->getBasename())) { - $extend_js = 'public/extensions/' . $extension . '/' . $extend_js_suffix; - $extend_css = 'public/extensions/' . $extension . '/' . $extend_css_suffix; - - if(is_readable(FHCPATH . $extend_js)) - { - array_push($tmpCustomJSModules, $extend_js); - } - - if(is_readable(FHCPATH . $extend_css)) - { - array_push($includes['customCSSs'], $extend_css); - } + $this->extensions[] = $fsitem->getBasename(); } } - array_push($tmpCustomJSModules, $item); } - $includes['customJSModules'] = $tmpCustomJSModules; - if($appscount > 0) + protected function prepareExtendedArrays() { - if(!isset($includes['customJSs'])) + $this->appscount = 0; + $this->initExtCustomCSSs(); + $this->extCustomJSModules = array(); + foreach($this->customJSModules as $item) { - $includes['customJSs'] = array(); + $matches = array(); + if(preg_match('#^public/(extensions/FHC-Core-.+)?js/apps/(.*)\.js$#', $item, $matches)) + { + $this->appscount++; + + $fhcextension = $matches[1]; + $app = $matches[2]; + + $extend_js_suffix = 'js/extend_app/' . $fhcextension . $app . '.js'; + $extend_css_suffix = 'css/extend_app/' . $fhcextension . $app . '.css'; + + foreach($this->extensions as $extension) + { + $extend_js = 'public/extensions/' . $extension . '/' . $extend_js_suffix; + $extend_css = 'public/extensions/' . $extension . '/' . $extend_css_suffix; + + if(is_readable(FHCPATH . $extend_js)) + { + array_push($this->extCustomJSModules, $extend_js); + } + + if(is_readable(FHCPATH . $extend_css)) + { + array_push($this->extCustomCSSs, $extend_css); + } + } + } + array_push($this->extCustomJSModules, $item); } - elseif(!is_array($includes['customJSs'])) + + if($this->appscount > 0) { - $includes['customJSs'] = array($includes['customJSs']); + $this->addFhcAppsJs(); } - array_push($includes['customJSs'], 'public/js/FhcApps.js'); } - return $includes; + protected function initExtCustomCSSs() + { + if(!isset($this->customCSSs)) + { + $this->extCustomCSSs = array(); + } + elseif(!is_array($this->customCSSs)) + { + $this->extCustomCSSs = array($this->customCSSs); + } + else + { + $this->extCustomCSSs = $this->customCSSs; + } + } + + protected function addFhcAppsJs() + { + if(!isset($this->customJSs)) + { + $this->extCustomJSs = array(); + } + elseif(!is_array($this->customJSs)) + { + $this->extCustomJSs = array($this->customJSs); + } + else + { + $this->extCustomJSs = $this->customJSs; + } + array_push($this->extCustomJSs, 'public/js/FhcApps.js'); + } } diff --git a/application/views/Cis/Documents.php b/application/views/Cis/Documents.php index fcafff57c..f34ce3fc1 100644 --- a/application/views/Cis/Documents.php +++ b/application/views/Cis/Documents.php @@ -1,9 +1,9 @@ 'Documents', 'tabulator5' => true, 'customJSModules' => ['public/js/apps/Cis/Documents.js'] -)); +); $this->load->view('templates/CISVUE-Header', $includesArray); ?> diff --git a/application/views/Cis/ProfilUpdate.php b/application/views/Cis/ProfilUpdate.php index 76e195b57..2e69208c7 100644 --- a/application/views/Cis/ProfilUpdate.php +++ b/application/views/Cis/ProfilUpdate.php @@ -1,5 +1,5 @@ 'Profil Änderungen', 'vue3' => true, 'primevue3' => true, @@ -16,7 +16,7 @@ $includesArray = extendableApps(array( 'customCSSs' => array( 'public/css/components/FilterComponent.css','public/css/components/FormUnderline.css' ) -)); +); if(defined("CIS4")) { diff --git a/application/views/CisRouterView/CisRouterView.php b/application/views/CisRouterView/CisRouterView.php index 44f3a3fcc..6ff428362 100644 --- a/application/views/CisRouterView/CisRouterView.php +++ b/application/views/CisRouterView/CisRouterView.php @@ -1,6 +1,6 @@ 'Cis4', 'axios027' => true, 'bootstrap5' => true, @@ -42,7 +42,7 @@ $includesArray = extendableApps(array( 'public/js/apps/Dashboard/Fhc.js', ), -)); +); $this->load->view('templates/CISVUE-Header', $includesArray); ?> diff --git a/application/views/LVVerwaltung.php b/application/views/LVVerwaltung.php index d2856ad3e..4cebae839 100644 --- a/application/views/LVVerwaltung.php +++ b/application/views/LVVerwaltung.php @@ -1,5 +1,5 @@ 'LVVerwaltung', 'axios027' => true, 'bootstrap5' => true, @@ -20,7 +20,7 @@ 'customJSModules' => [ 'public/js/apps/LVVerwaltung.js' ] - )); + ); $this->load->view('templates/FHC-Header', $includesArray); diff --git a/application/views/Studentenverwaltung.php b/application/views/Studentenverwaltung.php index 59b05063e..1cd28d735 100644 --- a/application/views/Studentenverwaltung.php +++ b/application/views/Studentenverwaltung.php @@ -1,5 +1,5 @@ 'Studentenverwaltung', 'axios027' => true, 'bootstrap5' => true, @@ -30,7 +30,7 @@ 'customJSModules' => [ 'public/js/apps/Studentenverwaltung.js' ] - )); + ); $this->load->view('templates/FHC-Header', $includesArray); ?> diff --git a/application/views/codex/bismeldestichtag.php b/application/views/codex/bismeldestichtag.php index fc0311674..37af16cc6 100644 --- a/application/views/codex/bismeldestichtag.php +++ b/application/views/codex/bismeldestichtag.php @@ -1,5 +1,5 @@ 'Bismeldestichtage', 'axios027' => true, 'bootstrap5' => true, @@ -11,7 +11,7 @@ 'customCSSs' => array('vendor/vuejs/vuedatepicker_css/main.css'), 'customJSs' => array('vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js'), 'customJSModules' => array('public/js/apps/Bismeldestichtag/Bismeldestichtag.js') - )); + ); $this->load->view('templates/FHC-Header', $includesArray); ?> diff --git a/application/views/lehre/Antrag/Create.php b/application/views/lehre/Antrag/Create.php index 56d1e0a28..00e41d1cd 100644 --- a/application/views/lehre/Antrag/Create.php +++ b/application/views/lehre/Antrag/Create.php @@ -1,5 +1,5 @@ 'Antrag auf Änderung des Studierendenstatus', 'cis' => true, 'vue3' => true, @@ -16,7 +16,7 @@ $sitesettings = extendableApps(array( ), 'customJSs' => array( ) -)); +); if(defined('CIS4')){ $this->load->view( diff --git a/application/views/lehre/Antrag/Leitung/List.php b/application/views/lehre/Antrag/Leitung/List.php index f6c95bc86..1225b16b6 100644 --- a/application/views/lehre/Antrag/Leitung/List.php +++ b/application/views/lehre/Antrag/Leitung/List.php @@ -2,7 +2,7 @@ use \DateTime as DateTime; -$sitesettings = extendableApps(array( +$sitesettings = array( 'title' => 'Anträge auf Änderung des Studierendenstatus', 'cis' => true, 'vue3' => true, @@ -25,7 +25,7 @@ $sitesettings = extendableApps(array( ), 'customJSs' => array( ) -)); +); $this->load->view( 'templates/FHC-Header', diff --git a/application/views/lehre/Antrag/Student/List.php b/application/views/lehre/Antrag/Student/List.php index 1b467e576..6d769dafe 100644 --- a/application/views/lehre/Antrag/Student/List.php +++ b/application/views/lehre/Antrag/Student/List.php @@ -1,5 +1,5 @@ 'Antrag auf Änderung des Studierendenstatus', 'cis' => true, 'vue3' => true, @@ -15,7 +15,7 @@ $sitesettings = extendableApps(array( ), 'customJSs' => array( ) -)); +); if(defined('CIS4')){ $this->load->view( diff --git a/application/views/lehre/Antrag/Wiederholung/Student.php b/application/views/lehre/Antrag/Wiederholung/Student.php index 65707cc7b..e51cfd1bc 100644 --- a/application/views/lehre/Antrag/Wiederholung/Student.php +++ b/application/views/lehre/Antrag/Wiederholung/Student.php @@ -1,5 +1,5 @@ 'Antrag Wiederholung vom Studium', 'cis' => true, 'vue3' => true, @@ -19,7 +19,7 @@ $sitesettings = extendableApps(array( ), 'customJSs' => array( ) -)); +); $this->load->view( 'templates/FHC-Header', diff --git a/application/views/lehre/lvplanung/lvTemplateUebersicht.php b/application/views/lehre/lvplanung/lvTemplateUebersicht.php index 8e47677f0..5c873486c 100644 --- a/application/views/lehre/lvplanung/lvTemplateUebersicht.php +++ b/application/views/lehre/lvplanung/lvTemplateUebersicht.php @@ -1,5 +1,5 @@ 'LV Template Übersicht', 'vue3' => true, 'axios027' => true, @@ -14,7 +14,7 @@ $includesArray = extendableApps(array( 'public/css/Fhc.css', 'public/css/lvTemplateUebersicht.css' ) -)); +); $this->load->view('templates/FHC-Header', $includesArray); ?> diff --git a/application/views/system/logs/logsViewer.php b/application/views/system/logs/logsViewer.php index 1d6b50394..ddfe855fe 100644 --- a/application/views/system/logs/logsViewer.php +++ b/application/views/system/logs/logsViewer.php @@ -1,5 +1,5 @@ 'Logs Viewer', 'axios027' => true, 'bootstrap5' => true, @@ -14,7 +14,7 @@ 'ui' => array('bitteEintragWaehlen') ), 'customJSModules' => array('public/js/apps/LogsViewer/LogsViewer.js'), - )); + ); $this->load->view('templates/FHC-Header', $includesArray); ?> diff --git a/application/views/templates/FHC-Footer.php b/application/views/templates/FHC-Footer.php index c816ebf2e..d2eb229f1 100644 --- a/application/views/templates/FHC-Footer.php +++ b/application/views/templates/FHC-Footer.php @@ -17,6 +17,7 @@ $use_vuejs_dev_version = $this->config->item('use_vuejs_dev_version'); // By default set the parameters to null + $customCSSs = isset($customCSSs) ? $customCSSs : null; $customJSs = isset($customJSs) ? $customJSs : null; $customJSModules = isset($customJSModules) ? $customJSModules : null; @@ -191,12 +192,13 @@ // NOTE: keep it as the last but one if ($addons === true) generateAddonsJSsInclude($calledPath.'/'.$calledMethod); - - + $extapphelper = ExtendableAppsHelper::getInstance(); + $extapphelper->init($customCSSs, $customJSs, $customJSModules); + // Eventually required JS // NOTE: keep it as the latest - generateJSsInclude($customJSs); - generateJSModulesInclude($customJSModules); + generateJSsInclude($extapphelper->getCustomJSs()); + generateJSModulesInclude($extapphelper->getCustomJSModules()); ?> diff --git a/application/views/templates/FHC-Header.php b/application/views/templates/FHC-Header.php index f7b5491a1..7b53cbf5d 100644 --- a/application/views/templates/FHC-Header.php +++ b/application/views/templates/FHC-Header.php @@ -9,6 +9,8 @@ $title = isset($title) ? $title : null; $refresh = isset($refresh) ? $refresh : null; $customCSSs = isset($customCSSs) ? $customCSSs : null; + $customJSs = isset($customJSs) ? $customJSs : null; + $customJSModules = isset($customJSModules) ? $customJSModules : null; $skipID = isset($skipID) ? $skipID : null; ?> @@ -132,8 +134,11 @@ //Tags if ($tags === true) generateCSSsInclude('public/css/tags.css'); + $extapphelper = ExtendableAppsHelper::getInstance(); + $extapphelper->init($customCSSs, $customJSs, $customJSModules); + // Eventually required CSS - generateCSSsInclude($customCSSs); // Eventually required CSS + generateCSSsInclude($extapphelper->getCustomCSSs()); // Eventually required CSS ?> From db75cd2f627703694b78d06cbaf5b7ccdbf97aae Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Tue, 3 Mar 2026 10:42:47 +0100 Subject: [PATCH 25/40] also skip email loop/relevant abgaben loop when every occurance is filtered out to avoid empty notification emails; --- application/controllers/jobs/AbgabetoolJob.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/application/controllers/jobs/AbgabetoolJob.php b/application/controllers/jobs/AbgabetoolJob.php index 9b59a72e7..b81053032 100644 --- a/application/controllers/jobs/AbgabetoolJob.php +++ b/application/controllers/jobs/AbgabetoolJob.php @@ -495,6 +495,10 @@ class AbgabetoolJob extends JOB_Controller // get all new or changed termine in interval $result = $this->_ci->PaabgabeModel->findAbgabenNewOrUpdatedSince($interval, $relevantTypes); $retval = getData($result); + if(!$retval) { + $this->_ci->logInfo("Keine Emails an Betreuer über neue oder veränderte Termine versandt"); + return; + } // group changed/new abgaben for projektarbeiten $projektarbeiten = []; @@ -557,6 +561,8 @@ class AbgabetoolJob extends JOB_Controller $anredeFillString = $data->anrede == "Herr" ? "r" : ""; $fullFormattedNameString = $data->first; + $relevantCounter = 0; // workaround to check if a betreuer needs to have any notification about relevant + // abgaben at all to avoid sending empty emails since we filter on certain conditions forEach($tupelArr as $tupel) { $projektarbeit_id = $tupel[0]; $betreuerRow = $tupel[1]; @@ -575,6 +581,8 @@ class AbgabetoolJob extends JOB_Controller continue; } + $relevantCounter++; + // format the Student Name $s = $relevantAbgaben[0]; $nameParts = []; @@ -633,6 +641,11 @@ class AbgabetoolJob extends JOB_Controller // done with building the change list, now send it $betreuerRow = $tupelArr[0][1]; + if($relevantCounter == 0) { + $this->_ci->logInfo('No Relevant Abgaben to notify Betreuer PersonID: "'.$betreuerRow->person_id.'".'); + continue; + } + $path = $this->_ci->config->item('URL_MITARBEITER'); $url = CIS_ROOT.$path; From 56a6aa993e7c8c9d8d01c3aebfdc39bd04994745 Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Tue, 3 Mar 2026 10:52:12 +0100 Subject: [PATCH 26/40] getMitarbeiterProjektarbeiten safeguard in case a person without any assigned betreuungen opens the page for some reason to avoid nasty confusing sql error messages from querying with empty parameters --- application/controllers/api/frontend/v1/Abgabe.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/application/controllers/api/frontend/v1/Abgabe.php b/application/controllers/api/frontend/v1/Abgabe.php index af598a345..0b82b7c20 100644 --- a/application/controllers/api/frontend/v1/Abgabe.php +++ b/application/controllers/api/frontend/v1/Abgabe.php @@ -511,10 +511,11 @@ class Abgabe extends FHCAPI_Controller return $projektarbeit->projektarbeit_id; }; $projektarbeiten_ids = array_map($mapFunc, $projektarbeiten->retval); - - $ret = $this->ProjektarbeitModel->getProjektarbeitenAbgabetermine($projektarbeiten_ids); - $projektabgaben = $this->getDataOrTerminateWithError($ret, 'general'); + if(count($projektarbeiten_ids) > 0) { + $ret = $this->ProjektarbeitModel->getProjektarbeitenAbgabetermine($projektarbeiten_ids); + $projektabgaben = $this->getDataOrTerminateWithError($ret, 'general'); + } forEach($projektarbeiten->retval as $pa) { From 7cd438d18839d1b059a2934144942baff9b907be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96sterreicher?= Date: Tue, 10 Mar 2026 11:47:24 +0100 Subject: [PATCH 27/40] Wenn Punkteeingabe aktiviert ist werden auch Punkte in der Excel Notenliste exportiert damit es beim Import von Spezialnoten (zb 18) nicht zu Problemen kommt --- cis/private/lehre/notenliste.xls.php | 41 ++++++++++++++++++---------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/cis/private/lehre/notenliste.xls.php b/cis/private/lehre/notenliste.xls.php index 6c8db5246..8202302a0 100644 --- a/cis/private/lehre/notenliste.xls.php +++ b/cis/private/lehre/notenliste.xls.php @@ -264,7 +264,7 @@ else tbl_bisio.bisio_id, tbl_bisio.bis, tbl_bisio.von, tbl_zeugnisnote.note,tbl_mobilitaet.mobilitaetstyp_kurzbz, (CASE WHEN bis.tbl_mobilitaet.studiensemester_kurzbz = vw_student_lehrveranstaltung.studiensemester_kurzbz THEN '1' ELSE '' END) as doubledegree, - tbl_note.lkt_ueberschreibbar, tbl_note.anmerkung + tbl_note.lkt_ueberschreibbar, tbl_note.anmerkung, tbl_zeugnisnote.punkte FROM campus.vw_student_lehrveranstaltung JOIN public.tbl_benutzer USING(uid) JOIN public.tbl_person USING(person_id) JOIN public.tbl_student ON(uid=student_uid) @@ -306,7 +306,14 @@ else && $elem->von < $stsemdatumbis && (anzahlTage($elem->von, $elem->bis) >= 30)) $inc.=' (o)'; - $note = $elem->note; + if(defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE==true) + { + $note = $elem->punkte; + } + else + { + $note = $elem->note; + } if($elem->lkt_ueberschreibbar == 'f') // angerechnet / intern angerechnet / nicht zugelassen { @@ -346,13 +353,16 @@ else { $resultPr = $output2[0]; $worksheet->write($lines,9, date('d.m.Y', strtotime($resultPr->datum)), $format_highlightright_date); - $worksheet->write($lines,10, $resultPr->note, $format_highlightright); + if(defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE==true) + $worksheet->write($lines,10, $resultPr->punkte, $format_highlightright); + else + $worksheet->write($lines,10, $resultPr->note, $format_highlightright); + } + else + { + $worksheet->write($lines,9, '', $format_highlightright_date); + $worksheet->write($lines,10, '', $format_highlightright); } - else - { - $worksheet->write($lines,9, '', $format_highlightright_date); - $worksheet->write($lines,10, '', $format_highlightright); - } } // Nachprüfung @@ -367,13 +377,16 @@ else { $resultPr = $output3[0]; $worksheet->write($lines,13, date('d.m.Y', strtotime($resultPr->datum)), $format_highlightright_date); - $worksheet->write($lines,14, $resultPr->note, $format_highlightright); + if(defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE==true) + $worksheet->write($lines,14, $resultPr->punkte, $format_highlightright); + else + $worksheet->write($lines,14, $resultPr->note, $format_highlightright); + } + else + { + $worksheet->write($lines,13, '', $format_highlightright_date); + $worksheet->write($lines,14, '', $format_highlightright); } - else - { - $worksheet->write($lines,13, '', $format_highlightright_date); - $worksheet->write($lines,14, '', $format_highlightright); - } } $i++; From 5ce0232890cc6ccc0b93fa441854bf535d396d13 Mon Sep 17 00:00:00 2001 From: Harald Bamberger Date: Wed, 11 Mar 2026 11:50:09 +0100 Subject: [PATCH 28/40] fix bug in archiv tab --- .../api/frontend/v1/stv/Dokumente.php | 4 ++++ .../Stv/Studentenverwaltung/Details/Archiv.js | 22 +++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/application/controllers/api/frontend/v1/stv/Dokumente.php b/application/controllers/api/frontend/v1/stv/Dokumente.php index 9f54d0aa4..b8c7830bd 100644 --- a/application/controllers/api/frontend/v1/stv/Dokumente.php +++ b/application/controllers/api/frontend/v1/stv/Dokumente.php @@ -753,6 +753,10 @@ class Dokumente extends FHCAPI_Controller ); $data = $this->getDataOrTerminateWithError($result); + if(!(is_array($data) && count($data) > 0)) + { + return null; + } $student = current($data); return $student->student_uid; diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js b/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js index 9477b08f4..756d9a774 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Archiv.js @@ -225,18 +225,32 @@ export default { return events; }, studentUids() { - if (this.modelValue.uid) + if(Array.isArray(this.modelValue)) + { + return this.modelValue.map(e => e.uid); + } + else if (this.modelValue.uid) { return [this.modelValue.uid]; } - return this.modelValue.map(e => e.uid); + else + { + return []; + } }, studentKzs(){ - if (this.modelValue.uid) + if(Array.isArray(this.modelValue)) + { + return this.modelValue.map(e => e.studiengang_kz); + } + else if (typeof this.modelValue.studiengang_kz !== 'undefined') { return [this.modelValue.studiengang_kz]; } - return this.modelValue.map(e => e.studiengang_kz); + else + { + return []; + } }, stg_kz(){ return this.studentKzs[0]; From 6cd4aebe8dc34df37b9756e4ea9aea1c8dc6922b Mon Sep 17 00:00:00 2001 From: Harald Bamberger Date: Wed, 11 Mar 2026 14:54:06 +0100 Subject: [PATCH 29/40] stv projektarbeit projektbetreuer use correct ref --- .../Details/Projektarbeit/Projektbetreuer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js index 433d745b4..ea8c742eb 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Projektarbeit/Projektbetreuer.js @@ -135,7 +135,7 @@ export default { await this.$p.loadCategory(['global', 'person', 'lehre', 'stv', 'projektarbeit', 'ui']); const setHeader = (field, text) => { - const col = this.$refs.table.tabulator.getColumn(field); + const col = this.$refs.projektbetreuerTable.tabulator.getColumn(field); if (!col) return; const el = col.getElement(); From b43f1ec920f76a07cc40241a075b1624920d06ec Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Wed, 11 Mar 2026 17:00:56 +0100 Subject: [PATCH 30/40] AbgabetoolAssistenz download latest uploaded file action button; UX changes Projektarbeit Tab Stv; fix stv form input bug after invalidation for selects; --- .../controllers/api/frontend/v1/Abgabe.php | 7 ++-- .../Cis/Abgabetool/AbgabetoolAssistenz.js | 32 ++++++++++++++- .../Cis/Abgabetool/AbgabetoolMitarbeiter.js | 4 +- public/js/components/Form/Input.js | 7 ++-- .../Details/Projektarbeit/Details.js | 10 +++-- .../Details/Projektarbeit/Projektbetreuer.js | 1 - system/phrasesupdate.php | 40 +++++++++++++++++++ 7 files changed, 89 insertions(+), 12 deletions(-) diff --git a/application/controllers/api/frontend/v1/Abgabe.php b/application/controllers/api/frontend/v1/Abgabe.php index 0b82b7c20..43dc18d1c 100644 --- a/application/controllers/api/frontend/v1/Abgabe.php +++ b/application/controllers/api/frontend/v1/Abgabe.php @@ -847,9 +847,10 @@ class Abgabe extends FHCAPI_Controller private function getProjektbetreuerEmailByProjektarbeitID($projektarbeit_id) { $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); $result = $this->ProjektarbeitModel->getProjektbetreuerEmail($projektarbeit_id); - $email = $this->getDataOrTerminateWithError($result, 'general'); - - return $email[0]->uid ? $email[0]->uid.'@'.DOMAIN : $email[0]->private_email; + if(count($result->retval) > 0) { + $email = getData($result); + return $email[0]->uid ? $email[0]->uid.'@'.DOMAIN : $email[0]->private_email; + } else return ''; } diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolAssistenz.js b/public/js/components/Cis/Abgabetool/AbgabetoolAssistenz.js index d5caf97a6..85ca901d9 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolAssistenz.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolAssistenz.js @@ -675,8 +675,20 @@ export const AbgabetoolAssistenz = { createButton('fa fa-timeline', 'abgabetool/c4termineTimeLine', () => this.openTimeline(val)) ); + if(val.latestTerminWithUpload) { + actionButtons.append( + createButton('fa fa-download', 'abgabetool/c4downloadLatestAbgabe', () => this.downloadAbgabe(val.latestTerminWithUpload.paabgabe_id, val.student_uid, val.projektarbeit_id)) + ) + } + return actionButtons; }, + downloadAbgabe(paabgabe_id, student_uid, projektarbeit_id) { + const url = `/api/frontend/v1/Abgabe/getStudentProjektarbeitAbgabeFile?paabgabe_id=${paabgabe_id}&student_uid=${student_uid}&projektarbeit_id=${projektarbeit_id}`; + + window.open(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + url) + // this.$api.call(ApiAbgabe.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid)) + }, undoSelection(cell) { // checks if cells row is selected and unselects -> imitates columns which dont trigger row selection @@ -780,6 +792,8 @@ export const AbgabetoolAssistenz = { // TODO: mehrsprachig englisch projekt.note_bez = opt.bezeichnung } + + const latestTerminWithUpload = this.findLatestTerminWithUpload(projekt) return { ...projekt, @@ -787,6 +801,7 @@ export const AbgabetoolAssistenz = { details: { student_uid: projekt.student_uid, projektarbeit_id: projekt.projektarbeit_id, + latestTerminWithUpload: latestTerminWithUpload ?? null }, pkz: this.buildPKZ(projekt), beurteilung: projekt.beurteilungLink ?? null, @@ -800,6 +815,15 @@ export const AbgabetoolAssistenz = { } }) }, + findLatestTerminWithUpload(projekt) { + const withAbgabedatumSorted = projekt?.abgabetermine?.filter(t => t.abgabedatum != null)?.sort((a,b) => a < b) + + if(withAbgabedatumSorted.length) { + return withAbgabedatumSorted[0] + } + + return null + }, createInfoString(data) { let str = ''; @@ -1413,9 +1437,12 @@ export const AbgabetoolAssistenz = {
-
+

{{$p.t('abgabetool/abgabetoolTitle')}}

+
+ +
+
+ +
projekarbeit.projektarbeit_id == details.projektarbeit_id) + const projektarbeiten = this.projektarbeiten?.retval ?? this.projektarbeiten + const pa = projektarbeiten.find(projekarbeit => projekarbeit.projektarbeit_id == details.projektarbeit_id) + let paIsBenotet = false if(pa.note !== undefined && pa.note !== null) { // check if the note is not defined as a non final projektarbeit note diff --git a/public/js/components/Form/Input.js b/public/js/components/Form/Input.js index 3c3fa45d5..4ad555ab7 100644 --- a/public/js/components/Form/Input.js +++ b/public/js/components/Form/Input.js @@ -170,6 +170,7 @@ export default { return this.$attrs.modelValue; }, set(v) { + this.clearValidationForThisName() if (!this.$attrs.hasOwnProperty('modelValue')) this.modelValueDummy = v; this.$emit('update:modelValue', v); @@ -242,9 +243,9 @@ export default { template: ` - - - + + 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4downloadLatestAbgabe', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Zuletzt getätigte Abgabe herunterladen", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Download latest uploaded File', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4termineTimeLine', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Zeitstrahl Termine', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Timeline Deadlines', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'abgabetool', From 40757322e78cfbd8c82ff8aa0227b04fa23e74bf Mon Sep 17 00:00:00 2001 From: kindlm Date: Wed, 11 Mar 2026 17:52:31 +0100 Subject: [PATCH 31/40] =?UTF-8?q?Spalte=20"FGM"=20(F=C3=B6rder-Guthaben-Mo?= =?UTF-8?q?nate)=20bei=20Prestudentstatus=20einblendbar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/student/studentdetailoverlay.xul.php | 5 +++++ include/prestudent.class.php | 1 + rdf/prestudentrolle.rdf.php | 1 + 3 files changed, 7 insertions(+) diff --git a/content/student/studentdetailoverlay.xul.php b/content/student/studentdetailoverlay.xul.php index 36740d209..c3bf8c191 100644 --- a/content/student/studentdetailoverlay.xul.php +++ b/content/student/studentdetailoverlay.xul.php @@ -798,6 +798,10 @@ echo ''; class="sortDirectionIndicator" sort="rdf:http://www.technikum-wien.at/prestudentrolle/rdf#updatevon" /> +