Merge branch 'feature-55991/FHC4_Studierendenverwaltung_Gruppen' into merge_FHC4_55354_55991_55992_60874_60875_61229_61230_61231

This commit is contained in:
Harald Bamberger
2025-05-21 13:30:07 +02:00
8 changed files with 415 additions and 1 deletions
@@ -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" .
@@ -0,0 +1,80 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class Gruppen extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'getGruppen' => ['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);
}
}
+33
View File
@@ -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 <https://www.gnu.org/licenses/>.
*/
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
};
}
}
+2
View File
@@ -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,
+8
View File
@@ -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);
}
}
@@ -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: `
<div class="stv-details-gruppen h-100 d-flex flex-column">
<gruppen-list ref="gruppen" :student="modelValue"></gruppen-list>
</div>`
};
@@ -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: '<i class="fa fa-check text-success"></i>',
crossElement: '<i class="fa fa-xmark text-danger"></i>'
}
},
{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 = '<i class="fa fa-xmark"></i>';
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: `
<div class="stv-details-gruppen h-100 pb-3">
<h5>{{$p.t('stv', 'tab_groups')}}</h5>
<core-filter-cmpt
ref="table"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
table-only
:side-menu="false"
reload
>
</core-filter-cmpt>
</div>
`
}
+84
View File
@@ -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',