diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index 455b1e8fc..564247688 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -99,6 +99,11 @@ class Config extends FHCAPI_Controller 'title' => $this->p->t('stv', 'tab_resources'), 'component' => './Stv/Studentenverwaltung/Details/Betriebsmittel.js' ]; + $result['groups'] = [ + 'title' => $this->p->t('stv', 'tab_groups'), + 'component' => './Stv/Studentenverwaltung/Details/Gruppen.js' + ]; + $result['grades'] = [ 'title' => $this->p->t('stv', 'tab_grades'), 'component' => './Stv/Studentenverwaltung/Details/Noten.js', @@ -318,7 +323,7 @@ class Config extends FHCAPI_Controller $title_eng = $this->p->t("global", "englisch"); $title_ff = $this->p->t("stv", "document_certificate"); $title_lv = $this->p->t("stv", "document_coursecertificate"); - + $link_ff = "documents/export/" . "zertifikat.rdf.php/" . "Zertifikat" . diff --git a/application/controllers/api/frontend/v1/stv/Gruppen.php b/application/controllers/api/frontend/v1/stv/Gruppen.php new file mode 100644 index 000000000..c30816f2a --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Gruppen.php @@ -0,0 +1,80 @@ + ['admin:r', 'assistenz:r'], + 'deleteGruppe' => ['admin:rw', 'assistenz:rw'], + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + // Load language phrases + $this->loadPhrases([ + 'ui', 'gruppenmanagement' + ]); + + // Load models + $this->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel'); + $this->load->model('organisation/Gruppe_model', 'GruppeModel'); + } + + public function getGruppen($student_uid) + { + $this->BenutzergruppeModel ->addSelect('gruppe_kurzbz'); + $this->BenutzergruppeModel ->addSelect('bezeichnung'); + $this->BenutzergruppeModel ->addSelect('generiert'); + $this->BenutzergruppeModel ->addSelect('uid'); + $this->BenutzergruppeModel ->addSelect('studiensemester_kurzbz'); + $this->BenutzergruppeModel ->addJoin('public.tbl_gruppe', 'gruppe_kurzbz'); + $this->BenutzergruppeModel-> addOrder('bezeichnung', 'ASC'); + + $result = $this->BenutzergruppeModel->loadWhere( + array( + 'uid' => $student_uid + ) + ); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + public function deleteGruppe() + { + $student_uid = $this->input->post('id'); + $gruppe_kurzbz = $this->input->post('gruppe_kurzbz'); + + //Validate if automatic group generation + $result = $this->GruppeModel-> loadWhere( + array( + 'gruppe_kurzbz' => $gruppe_kurzbz + ) + ); + $data = $this->getDataOrTerminateWithError($result); + $generation = current($data); + + if($generation->generiert) + { + $this->terminateWithError($this->p->t('gruppenmanagement', 'error_deleteGeneratedGroups'), self::ERROR_TYPE_GENERAL); + } + + $result = $this->BenutzergruppeModel->delete( + array( + 'gruppe_kurzbz' => $gruppe_kurzbz, + 'uid' => $student_uid + ) + ); + + $data = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess($data); + } +} diff --git a/public/js/api/factory/stv/group.js b/public/js/api/factory/stv/group.js new file mode 100644 index 000000000..b395fbf43 --- /dev/null +++ b/public/js/api/factory/stv/group.js @@ -0,0 +1,33 @@ +/** + * 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 { + getGruppen(id) { + return { + method: 'get', + url: 'api/frontend/v1/stv/Gruppen/getGruppen/' + id + }; + }, + deleteGroup(params) { + return { + method: 'post', + url: 'api/frontend/v1/stv/Gruppen/deleteGruppe/', + params + }; + } +} + diff --git a/public/js/api/stv.js b/public/js/api/stv.js index f93c46bcf..63e53f4fb 100644 --- a/public/js/api/stv.js +++ b/public/js/api/stv.js @@ -2,6 +2,7 @@ import verband from './stv/verband.js'; import students from './stv/students.js'; import filter from './stv/filter.js'; import konto from './stv/konto.js'; +import group from './stv/group.js'; import kontakt from './stv/kontakt.js'; import prestudent from './stv/prestudent.js'; import status from './stv/status.js'; @@ -17,6 +18,7 @@ export default { students, filter, konto, + group, kontakt, prestudent, status, diff --git a/public/js/api/stv/group.js b/public/js/api/stv/group.js new file mode 100644 index 000000000..af6e6e122 --- /dev/null +++ b/public/js/api/stv/group.js @@ -0,0 +1,8 @@ +export default { + getGruppen(url, config, params) { + return this.$fhcApi.get('api/frontend/v1/stv/Gruppen/getGruppen/' + params.id); + }, + deleteGroup(params) { + return this.$fhcApi.post('api/frontend/v1/stv/Gruppen/deleteGruppe/', params); + } +} \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Gruppen.js b/public/js/components/Stv/Studentenverwaltung/Details/Gruppen.js new file mode 100644 index 000000000..96fc6c772 --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Gruppen.js @@ -0,0 +1,20 @@ +import GruppenList from './Gruppen/Gruppen.js'; + +export default { + name: 'TabGroups', + components: { + GruppenList + }, + props: { + modelValue: Object + }, + methods: { + reload() { + this.$refs.gruppen.$refs.table.reloadTable(); + } + }, + template: ` +
+ +
` +}; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Gruppen/Gruppen.js b/public/js/components/Stv/Studentenverwaltung/Details/Gruppen/Gruppen.js new file mode 100644 index 000000000..67f422efb --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Gruppen/Gruppen.js @@ -0,0 +1,182 @@ +import {CoreFilterCmpt} from "../../../../filter/Filter.js"; + +import ApiStvGroups from '../../../../../api/factory/stv/group.js'; + +export default { + name: 'TblGroups', + components: { + CoreFilterCmpt, + }, + inject: { + currentSemester: { + from: 'currentSemester', + }, + }, + props: { + student: Object + }, + data() { + return { + tabulatorOptions: { + ajaxURL: 'dummy', + ajaxRequestFunc: () => this.$api.call( + ApiStvGroups.getGruppen(this.student.uid) + ), + ajaxResponse: (url, params, response) => response.data, + initialFilter: [ + {field: "uid", type: "=", value: this.student.uid}, + [ + {field: "studiensemester_kurzbz", type: "=", value: this.currentSemester}, + {field: "studiensemester_kurzbz", type: "=", value: null} + ] + ], + columns: [ + {title: "Gruppe", field: "gruppe_kurzbz"}, + {title: "Bezeichnung", field: "bezeichnung"}, + {title: "Semester", field: "studiensemester_kurzbz"}, + { + title: "automatisch generiert", + field: "generiert", + formatter: "tickCross", + hozAlign: "center", + formatterParams: { + tickElement: '', + crossElement: '' + } + }, + {title: "UID", field: "uid"}, + { + title: 'Aktionen', field: 'actions', + minWidth: 150, // Ensures Action-buttons will be always fully displayed + formatter: (cell, formatterParams, onRendered) => { + const container = document.createElement('div'); + container.className = "d-flex gap-2"; + + const data = cell.getData(); + + const button = document.createElement('button'); + button.className = 'btn btn-outline-secondary btn-action'; + button.innerHTML = ''; + button.title = this.$p.t('ui', 'loeschen'); + button.addEventListener('click', () => + this.actionDeleteGroup(data.gruppe_kurzbz) + ); + if (data.generiert) + button.disabled = true; + container.append(button); + + return container; + }, + frozen: true + }, + ], + layout: 'fitDataFill', + height: 'auto', + selectable: true, + index: 'group_id', + persistenceID: 'stv-details-gruppe' + }, + tabulatorEvents: [ + { + event: 'tableBuilt', + handler: async () => { + + await this.$p.loadCategory(['global', 'person', 'stv', 'ui', 'gruppenmanagement']); + + let cm = this.$refs.table.tabulator.columnManager; + + cm.getColumnByField('gruppe_kurzbz').component.updateDefinition({ + title: this.$p.t('gruppenmanagement', 'gruppe') + }); + + cm.getColumnByField('bezeichnung').component.updateDefinition({ + title: this.$p.t('ui', 'bezeichnung') + }); + + cm.getColumnByField('generiert').component.updateDefinition({ + title: this.$p.t('gruppenmanagement', 'automatisch_generiert') + }); + + cm.getColumnByField('uid').component.updateDefinition({ + title: this.$p.t('ui', 'student_uid') + }); + + //Interference with Filter if not commented out + /* + cm.getColumnByField('studiensemester_kurzbz').component.updateDefinition({ + title: this.$p.t('lehre', 'studiensemester') + });*/ + + } + } + ], + } + }, + methods: { + actionDeleteGroup(gruppe_kurzbz) { + this.$fhcAlert + .confirmDelete() + .then(result => result + ? gruppe_kurzbz + : Promise.reject({handled: true})) + .then(this.deleteGroup) + .catch(this.$fhcAlert.handleSystemError); + + }, + deleteGroup(gruppe_kurzbz) { + const group_id = { + id: this.student.uid, + gruppe_kurzbz: gruppe_kurzbz + }; + + return this.$api + .call(ApiStvGroups.deleteGroup(group_id)) + .then(response => { + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + }).catch(this.$fhcAlert.handleSystemError) + .finally(() => { + window.scrollTo(0, 0); + this.reload(); + }); + }, + reload() { + this.$refs.table.reloadTable(); + }, + }, + watch: { + currentSemester(newVal) { + if (newVal) { + + this.$refs.table.tabulator.clearFilter(); // Clear old filters + + this.$refs.table.tabulator.setFilter([ + {field: "uid", type: "=", value: this.student.uid}, + [ + {field: "studiensemester_kurzbz", type: "=", value: newVal}, + {field: "studiensemester_kurzbz", type: "=", value: null} + ] + ]); + + + } + }, + student() { + this.$refs.table.reloadTable(); + } + }, + template: ` +
+
{{$p.t('stv', 'tab_groups')}}
+ + + +
+ ` +} \ No newline at end of file diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index cb13d0c58..1c8c07f23 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -39869,6 +39869,90 @@ array( ) ) ), + //////////// FHC4 Phrases Gruppen Start //////////// + array( + 'app' => 'core', + 'category' => 'stv', + 'phrase' => 'tab_groups', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Gruppen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Groups', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'gruppenmanagement', + 'phrase' => 'gruppe', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Gruppe', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Group', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'gruppenmanagement', + 'phrase' => 'automatisch_generiert', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'automatisch generiert', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'automatically generated', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'gruppenmanagement', + 'phrase' => 'error_deleteGeneratedGroups', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Automatisch generierte Gruppenzuordnungen können nicht gelöscht werden.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Automatically generated group assignments cannot be deleted.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ) + //////////// FHC4 Phrases Gruppen End //////////// + + ), // FHC4 Phrases CleanUpTasks End array( 'app' => 'core',