From cc3da1439d28e2599fb087e91e512946e1972ffc Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 5 Nov 2025 11:06:45 +0100 Subject: [PATCH 01/13] StV: add user menu --- application/views/Studentenverwaltung.php | 2 + public/css/Studentenverwaltung.css | 6 ++ .../js/components/Stv/Studentenverwaltung.js | 35 +++++++++++ public/js/components/navigation/Language.js | 62 +++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 public/js/components/navigation/Language.js diff --git a/application/views/Studentenverwaltung.php b/application/views/Studentenverwaltung.php index 01e611657..16b8c0045 100644 --- a/application/views/Studentenverwaltung.php +++ b/application/views/Studentenverwaltung.php @@ -53,6 +53,8 @@ $configArray = [ active-addons="" stv-root="" cis-root="" + avatar-url="" + logout-url="" :permissions="" :config="" > diff --git a/public/css/Studentenverwaltung.css b/public/css/Studentenverwaltung.css index bb2588926..d92e3dfac 100644 --- a/public/css/Studentenverwaltung.css +++ b/public/css/Studentenverwaltung.css @@ -41,6 +41,12 @@ html { width: 0%; } +#nav-user-btn img { + object-fit: contain; + height: 2.5rem; + width: 2.5rem; +} + .tabulator-row.disabled.tabulator-row-odd .tabulator-cell { color: var(--gray-400); } diff --git a/public/js/components/Stv/Studentenverwaltung.js b/public/js/components/Stv/Studentenverwaltung.js index d0543ad59..c97d7a0bf 100644 --- a/public/js/components/Stv/Studentenverwaltung.js +++ b/public/js/components/Stv/Studentenverwaltung.js @@ -16,6 +16,7 @@ */ import CoreSearchbar from "../searchbar/searchbar.js"; +import NavLanguage from "../navigation/Language.js"; import VerticalSplit from "../verticalsplit/verticalsplit.js"; import StvVerband from "./Studentenverwaltung/Verband.js"; import StvList from "./Studentenverwaltung/List.js"; @@ -31,6 +32,7 @@ export default { name: 'Studentenverwaltung', components: { CoreSearchbar, + NavLanguage, VerticalSplit, StvVerband, StvList, @@ -43,6 +45,8 @@ export default { permissions: Object, stvRoot: String, cisRoot: String, + avatarUrl: String, + logoutUrl: String, activeAddons: String, // semicolon separated list of active addons url_studiensemester_kurzbz: String, url_mode: String, @@ -355,6 +359,37 @@ export default { :searchfunction="searchfunction" class="searchbar position-relative w-100" > +
diff --git a/public/js/components/navigation/Language.js b/public/js/components/navigation/Language.js new file mode 100644 index 000000000..4d26dadc0 --- /dev/null +++ b/public/js/components/navigation/Language.js @@ -0,0 +1,62 @@ +/** + * 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 . + */ + +export default { + emits: [ + 'changed' + ], + props: { + activeClass: { + type: String, + default: 'active' + }, + itemClass: { + type: [String, Array, Object], + default: '' + } + }, + data() { + return { + languages: FHC_JS_DATA_STORAGE_OBJECT.server_languages + }; + }, + methods:{ + onChange(lang) { + if (this.languages.some(l => l.sprache === lang)) { + this.$p + .setLanguage(lang) + .then(() => { + if (document.querySelector('[cis4Reload]')) + window.location.reload(); + else + this.$emit('changed', lang); + }); + } + } + }, + template: /*html*/` + ` +}; \ No newline at end of file From 601110913281ee722d8cab3dbb9eb6a3ffe899ed Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 5 Nov 2025 11:44:25 +0100 Subject: [PATCH 02/13] Fix language on details tabs --- .../Stv/Studentenverwaltung/Details.js | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/public/js/components/Stv/Studentenverwaltung/Details.js b/public/js/components/Stv/Studentenverwaltung/Details.js index 8222d637e..2c141754e 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details.js +++ b/public/js/components/Stv/Studentenverwaltung/Details.js @@ -37,25 +37,34 @@ export default { return this.configStudents; } }, + watch: { + '$p.user_language.value'(n, o) { + if (n !== o && o !== undefined) + this.loadConfig(); + } + }, methods: { + loadConfig() { + this.$api + .call(ApiStvApp.configStudent()) + .then(result => { + this.configStudent = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + this.$api + .call(ApiStvApp.configStudents()) + .then(result => { + this.configStudents = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + }, reload() { if (this.$refs.tabs?.$refs?.current?.reload) this.$refs.tabs.$refs.current.reload(); } }, created() { - this.$api - .call(ApiStvApp.configStudent()) - .then(result => { - this.configStudent = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); - this.$api - .call(ApiStvApp.configStudents()) - .then(result => { - this.configStudents = result.data; - }) - .catch(this.$fhcAlert.handleSystemError); + this.loadConfig(); }, template: `
From a97a1765224bfb3f54345e8e2c58f35d8692904e Mon Sep 17 00:00:00 2001 From: chfhtw Date: Wed, 5 Nov 2025 16:47:31 +0100 Subject: [PATCH 03/13] use phrasen in stv list --- .../Stv/Studentenverwaltung/List.js | 81 ++++++ system/phrasesupdate.php | 260 ++++++++++++++++++ 2 files changed, 341 insertions(+) diff --git a/public/js/components/Stv/Studentenverwaltung/List.js b/public/js/components/Stv/Studentenverwaltung/List.js index 67cada523..1ac68e346 100644 --- a/public/js/components/Stv/Studentenverwaltung/List.js +++ b/public/js/components/Stv/Studentenverwaltung/List.js @@ -1,6 +1,8 @@ import {CoreFilterCmpt} from "../../filter/Filter.js"; import ListNew from './List/New.js'; +import { capitalize } from '../../../helpers/StringHelpers.js'; + export default { name: "ListPrestudents", @@ -165,7 +167,85 @@ export default { currentEndpointRawUrl: '' } }, + watch: { + '$p.user_language.value'(n, o) { + if (n !== o && o !== undefined && this.$refs.table.tableBuilt) { + this.translateTabulator(); + } + } + }, methods: { + translateTabulator() { + let cm = this.$refs.table.tabulator.columnManager; + this.$p + .loadCategory(['global', 'person', 'lehre', 'ui', 'profilUpdate', 'admission', 'stv']) + .then(() => { + const translations = { + uid: capitalize(this.$p.t('person/uid')), + titelpre: capitalize(this.$p.t('person/titelpre')), + nachname: capitalize(this.$p.t('person/nachname')), + vorname: capitalize(this.$p.t('person/vorname')), + wahlname: capitalize(this.$p.t('person/wahlname')), + vornamen: capitalize(this.$p.t('person/vornamen')), + titelpost: capitalize(this.$p.t('person/titelpost')), + ersatzkennzeichen: capitalize(this.$p.t('person/ersatzkennzeichen')), + gebdatum: capitalize(this.$p.t('person/geburtsdatum')), + geschlecht: capitalize(this.$p.t('person/geschlecht')), + semester: capitalize(this.$p.t('lehre/sem')), + verband: capitalize(this.$p.t('lehre/verb')), + gruppe: capitalize(this.$p.t('lehre/grp')), + studiengang: capitalize(this.$p.t('lehre/studiengang')), + studiengang_kz: capitalize(this.$p.t('lehre/studiengang_kz')), + matrikelnr: capitalize(this.$p.t('person/personenkennzeichen')), + person_id: capitalize(this.$p.t('person/person_id')), + status: capitalize(this.$p.t('global/status')), + status_datum: capitalize(this.$p.t('profilUpdate/statusDate')), + status_bestaetigung: capitalize(this.$p.t('global/status_bestaetigung')), + mail_privat: capitalize(this.$p.t('person/email_private')), + mail_intern: capitalize(this.$p.t('person/email_intern')), + anmerkungen: capitalize(this.$p.t('stv/notes_person')), + anmerkung: capitalize(this.$p.t('stv/notes_prestudent')), + orgform_kurzbz: capitalize(this.$p.t('lehre/orgform')), + aufmerksamdurch_kurzbz: capitalize(this.$p.t('person/aufmerksamDurch')), + punkte: capitalize(this.$p.t('admission/gesamtpunkte')), + aufnahmegruppe_kurzbz: capitalize(this.$p.t('stv/aufnahmegruppe_kurzbz')), + dual: capitalize(this.$p.t('lehre/dual_short')), + matr_nr: capitalize(this.$p.t('person/matrikelnummer')), + studienplan_bezeichnung: capitalize(this.$p.t('lehre/studienplan')), + prestudent_id: capitalize(this.$p.t('ui/prestudent_id')), + priorisierung_relativ: capitalize(this.$p.t('lehre/prioritaet')), + mentor: capitalize(this.$p.t('stv/mentor')), + bnaktiv: capitalize(this.$p.t('person/aktiv')) + }; + + /** NOTE(chris): + * use this approach because updateDefinition + * on the Tabulator columns is way slower and + * freezes up the GUI. + */ + // Overwrite definition for column show/hide + this.$refs.table.tabulator.getColumns().forEach(col => { + const trans = translations[col.getField()]; + if (!trans) + return; + col.getDefinition().title = trans; + }); + // Overwrite node in dom + this.$refs.table.tabulator.element + .querySelectorAll('.tabulator-col[tabulator-field]') + .forEach(el => { + const field = el.getAttribute('tabulator-field'); + if (!translations[field]) + return; + + const title = el.querySelector('.tabulator-col-title'); + if (!title) + return; + + title.innerText = translations[field]; + }); + }); + }, reload() { this.$refs.table.reloadTable(); }, @@ -327,6 +407,7 @@ export default { */` :new-btn-label="$p.t('stv/action_new')" @click:new="actionNewPrestudent" + @table-built="translateTabulator" >