added Projektarbeit tab to Studierendenverwaltung, adding, editing, deleting of Projektarbeiten now possible

This commit is contained in:
Alexei Karpenko
2025-05-07 18:36:51 +02:00
parent da86575e65
commit 405062f549
10 changed files with 2230 additions and 10 deletions
@@ -123,6 +123,11 @@ class Config extends FHCAPI_Controller
'config' => $config['finalexam']
];
$result['projektarbeit'] = [
'title' => $this->p->t('stv', 'tab_projektarbeit'),
'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js'
];
$result['mobility'] = [
'title' => $this->p->t('stv', 'tab_mobility'),
'component' => './Stv/Studentenverwaltung/Details/Mobility.js'
@@ -0,0 +1,334 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class Projektarbeit extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'getProjektarbeit' => ['admin:r', 'assistenz:r'],
'loadProjektarbeit' => ['admin:r', 'assistenz:r'],
'insertProjektarbeit' => ['admin:rw', 'assistenz:rw'],
'updateProjektarbeit' => ['admin:rw', 'assistenz:rw'],
'deleteProjektarbeit' => ['admin:rw', 'assistenz:rw'],
'getTypenProjektarbeit' => ['admin:r', 'assistenz:r'],
'getFirmen' => ['admin:r', 'assistenz:r'],
'getLehrveranstaltungen' => ['admin:r', 'assistenz:r'],
'getNoten' => ['admin:rw', 'assistenz:rw']
]);
// Load Libraries
$this->load->library('form_validation');
// Load language phrases
$this->loadPhrases([
'ui',
'person',
'projektarbeit'
]);
// Load models
$this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel');
$this->load->model('education/Projekttyp_model', 'ProjekttypModel');
$this->load->model('education/Paabgabe_model', 'PaabgabeModel');
$this->load->model('ressource/Firma_model', 'FirmaModel');
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('education/Note_model', 'NoteModel');
$this->load->model('education/Projektbetreuer_model', 'BetreuerModel');
// load libraries
$this->load->library('PermissionLib');
}
public function getProjektarbeit()
{
$student_uid = $this->input->get('uid');
if (!isset($student_uid)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL);
$result = $this->ProjektarbeitModel->getProjektarbeit($student_uid);
if (isError($result))
{
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
if (!hasData($result)) $this->terminateWithSuccess([]);
$projektarbeiten = getData($result);
foreach ($projektarbeiten as $projektarbeit)
{
$projektarbeit_id = $projektarbeit->projektarbeit_id;
$abgabeRes = $this->PaabgabeModel->getEndabgabe($projektarbeit_id);
if (isError($abgabeRes)) $this->terminateWithError(getError($abgabeRes), self::ERROR_TYPE_GENERAL);
if (hasData($abgabeRes))
{
$paabgabe = getData($abgabeRes)[0];
$projektarbeit->abgabedatum = $paabgabe->abgabedatum;
}
}
$this->terminateWithSuccess($projektarbeiten);
}
public function loadProjektarbeit()
{
$projektarbeit_id = $this->input->get('projektarbeit_id');
if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id)) return $this->terminateWithError('Projektarbeit Id missing', self::ERROR_TYPE_GENERAL);
$this->ProjektarbeitModel->addSelect(
'lehre.tbl_projektarbeit.projektarbeit_id, titel, titel_english, themenbereich, projekttyp_kurzbz, firma_id,
lehrveranstaltung_id, lehreinheit_id, beginn, note, final, freigegeben, tbl_projektarbeit.anmerkung, fa.name AS firma_name'
);
$this->ProjektarbeitModel->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id');
$this->ProjektarbeitModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id');
$this->ProjektarbeitModel->addJoin('public.tbl_firma fa', 'firma_id');
$result = $this->ProjektarbeitModel->loadWhere(
array('projektarbeit_id' => $projektarbeit_id)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(current($data));
}
public function insertProjektarbeit()
{
$student_uid = $this->input->post('uid');
if (!$student_uid) return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL);
if (!$this->_hasBerechtigungForStudent($student_uid))
return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]);
$formData = $this->input->post('formData');
$this->addMeta('form', $formData);
if ($this->_validate($formData) == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$result = $this->ProjektarbeitModel->insert(
array_merge($formData, ['insertamum' => date('c'), 'insertvon' => getAuthUID(), 'student_uid' => $student_uid])
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function updateProjektarbeit()
{
$projektarbeit_id = $this->input->post('projektarbeit_id');
if (!$projektarbeit_id || !is_numeric($projektarbeit_id))
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL);
if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id))
return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]);
$formData = $this->input->post('formData');
if ($this->_validate($formData) == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$result = $this->ProjektarbeitModel->update(
$projektarbeit_id,
array_merge($formData, ['updateamum' => date('c'), 'updatevon' => getAuthUID()])
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function deleteProjektarbeit()
{
$projektarbeit_id = $this->input->post('projektarbeit_id');
if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id))
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID'], self::ERROR_TYPE_GENERAL));
if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id))
return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]);
$validate = $this->_validateDelete($projektarbeit_id);
if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL);
$result = $this->ProjektarbeitModel->delete(
array('projektarbeit_id' => $projektarbeit_id)
);
if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
if (!hasData($result))
{
$this->outputJson($result);
}
return $this->terminateWithSuccess(current(getData($result)) ? : null);
}
public function getTypenProjektarbeit()
{
$result = $this->ProjekttypModel->loadWhere(['aktiv' => true]);
if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
return $this->terminateWithSuccess(hasData($result) ? getData($result) : []);
}
public function getFirmen()
{
$searchString = $this->input->get('searchString');
if (!isset($searchString)) $this->terminateWithError($this->p->t('projektarbeit', 'error_searchStringMissing', self::ERROR_TYPE_GENERAL));
$result = $this->FirmaModel->searchFirmen($searchString, $aktiv = true);
if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
return $this->terminateWithSuccess(hasData($result) ? getData($result) : []);
}
public function getLehrveranstaltungen()
{
$student_uid = $this->input->get('student_uid');
$studiengang_kz = $this->input->get('studiengang_kz');
$studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz');
$additional_lehrveranstaltung_id = $this->input->get('additional_lehrveranstaltung_id');
if (!isset($student_uid)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL);
if (!isset($studiensemester_kurzbz)) $this->terminateWithError('Studiensemster missing', self::ERROR_TYPE_GENERAL);
$lvsResult = $this->LehrveranstaltungModel->getLvsForProjektarbeit($student_uid, $studiengang_kz, $additional_lehrveranstaltung_id);
if (isError($lvsResult)) return $this->terminateWithError($lvsResult, self::ERROR_TYPE_GENERAL);
$lvs = hasData($lvsResult) ? getData($lvsResult) : [];
foreach ($lvs as $lv)
{
$lehreinheiten = $this->LehreinheitModel->getLesForLv(
$lv->lehrveranstaltung_id, $studiensemester_kurzbz
);
foreach ($lehreinheiten as $lehreinheit)
{
if (!isEmptyArray($lehreinheit->lektoren))
{
$this->MitarbeiterModel->addSelect('kurzbz');
$this->MitarbeiterModel->db->where_in('tbl_mitarbeiter.mitarbeiter_uid', $lehreinheit->lektoren);
$maResult = $this->MitarbeiterModel->load();
if (isError($maResult)) return $this->terminateWithError($lvsResult, self::ERROR_TYPE_GENERAL);
$lehreinheit->lektoren = array_column(getData($maResult), 'kurzbz');
}
}
$lv->lehreinheiten = $lehreinheiten;
}
return $this->terminateWithSuccess($lvs);
}
public function getNoten()
{
$result = $this->NoteModel->load();
if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
return $this->terminateWithSuccess(hasData($result) ? getData($result) : []);
}
/**
*
* @param
* @return object success or error
*/
private function _validate($formData)
{
$this->form_validation->set_data($formData);
$this->form_validation->set_rules('titel', 'Titel', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Titel'])
]);
$this->form_validation->set_rules('projekttyp_kurzbz', 'Projekttyp', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Projekttyp'])
]);
$this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'required|numeric', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']),
//'matches' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']),
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit'])
]);
$this->form_validation->set_rules('beginn', 'Beginn', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Beginn'])
]);
return $this->form_validation->run();
}
/**
*
* @param
* @return object success or error
*/
private function _validateDelete($projektarbeit_id)
{
$this->BetreuerModel->addSelect('1');
$result = $this->BetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]);
if (isError($result)) return $result;
if (hasData($result)) return error($this->p->t('projektarbeit', 'error_betreuerNichtGeloescht'));
$this->PaabgabeModel->addSelect('1');
$result = $this->PaabgabeModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]);
if (isError($result)) return $result;
if (hasData($result)) return error($this->p->t('projektarbeit', 'error_paabgabeNichtGeloescht'));
return success();
}
private function _hasBerechtigungForStudent($student_uid)
{
if (!$student_uid)
return false;
$this->load->model('crm/Student_model', 'StudentModel');
$this->StudentModel->addSelect('studiengang_kz');
$result = $this->StudentModel->load([$student_uid]);
if (isError($result) || !hasData($result))
return false;
$studiengang_kz = getData($result)[0]->studiengang_kz;
if ($this->permissionlib->isBerechtigt('admin', 'suid', $studiengang_kz))
return true;
if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $studiengang_kz))
return true;
return false;
}
}
@@ -988,4 +988,61 @@ class Lehrveranstaltung_model extends DB_Model
return $this->execQuery($qry, $params);
}
/**
* Gets Lehrveranstaltungen for a student, as needed for a Projektarbeit.
* @param student_uid
* @param studiengang_kz optional, all Lvs of this Studiengang will be included
* @param additional_lehrveranstaltung_id optional, this lv will be added to result
* @return object success or error
*/
public function getLvsForProjektarbeit($student_uid, $studiengang_kz = null, $additional_lehrveranstaltung_id = null)
{
$params = array($student_uid, $student_uid);
$qry = "
SELECT *
FROM
lehre.tbl_lehrveranstaltung
WHERE
(
lehrveranstaltung_id IN (
SELECT
lehrveranstaltung_id
FROM
campus.vw_student_lehrveranstaltung
WHERE
uid=?
UNION
SELECT
lehrveranstaltung_id
FROM
lehre.tbl_zeugnisnote
WHERE
student_uid=?
)";
if (isset($studiengang_kz))
{
$params[] = $studiengang_kz;
$qry .= " OR (studiengang_kz = ? AND semester IS NOT NULL)";
}
if (isset($additional_lehrveranstaltung_id))
{
$params[] = $additional_lehrveranstaltung_id;
$qry .= " OR lehrveranstaltung_id = ?";
}
$qry .= "
)
AND projektarbeit = TRUE
ORDER BY
semester, bezeichnung";
return $this->execQuery($qry, $params);
}
}
@@ -24,15 +24,17 @@ class Projektarbeit_model extends DB_Model
public function getProjektarbeit($student_uid, $studiengang_kz = null, $studiensemester_kurzbz = null, $projekttyp = null, $final = null)
{
$qry = "SELECT
tbl_projektarbeit.* , tbl_projekttyp.bezeichnung
tbl_projektarbeit.*, tbl_projekttyp.bezeichnung,
tbl_lehreinheit.studiensemester_kurzbz, tbl_lehrveranstaltung.lehrveranstaltung_id,
tbl_firma.name AS firma_name
FROM
lehre.tbl_projektarbeit
JOIN
lehre.tbl_projekttyp USING (projekttyp_kurzbz), lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung
lehre.tbl_projekttyp USING (projekttyp_kurzbz), lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, public.tbl_firma
WHERE
tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND
tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND
tbl_projektarbeit.firma_id = tbl_firma.firma_id AND
tbl_projektarbeit.student_uid = ?";
$params = array($student_uid);
@@ -69,4 +71,30 @@ class Projektarbeit_model extends DB_Model
return $this->execQuery($qry, $params);
}
/**
*
* @param
* @return object success or error
*/
public function hasBerechtigungForProjektarbeit($projektarbeit_id)
{
if (!$projektarbeit_id || !is_numeric($projektarbeit_id))
return false;
$this->ProjektarbeitModel->addSelect('studiengang_kz');
$this->ProjektarbeitModel->addJoin('public.tbl_student', 'student_uid');
$result = $this->ProjektarbeitModel->load($projektarbeit_id);
if (isError($result) || !hasData($result))
return false;
$studiengang_kz = getData($result)[0]->studiengang_kz;
if ($this->permissionlib->isBerechtigt('admin', 'suid', $studiengang_kz))
return true;
if ($this->permissionlib->isBerechtigt('assistenz', 'suid', $studiengang_kz))
return true;
return false;
}
}
+14 -7
View File
@@ -12,17 +12,24 @@ class Firma_model extends DB_Model
$this->pk = 'firma_id';
}
public function searchFirmen($filter)
public function searchFirmen($filter, $aktiv = null)
{
$params = [];
$filter = strtoLower($filter);
$qry = "
SELECT
SELECT
f.name, f.firma_id
FROM
public.tbl_firma f
WHERE
lower (f.name) LIKE '%". $this->db->escape_like_str($filter)."%'";
FROM
public.tbl_firma f
WHERE
lower (f.name) LIKE '%". $this->db->escape_like_str($filter)."%'";
return $this->execQuery($qry);
if (isset($aktiv) && is_bool($aktiv))
{
$params[] = $aktiv;
$qry .= " AND aktiv = ?";
}
return $this->execQuery($qry, $params);
}
}
@@ -0,0 +1,80 @@
/**
* 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 {
getProjektarbeit(uid) {
return {
method: 'get',
url: 'api/frontend/v1/stv/projektarbeit/getProjektarbeit',
params: { uid }
};
},
getTypenProjektarbeit() {
return {
method: 'get',
url: 'api/frontend/v1/stv/projektarbeit/getTypenProjektarbeit'
};
},
getFirmen(searchString) {
return {
method: 'get',
url: 'api/frontend/v1/stv/projektarbeit/getFirmen',
params: {searchString}
};
},
getLehrveranstaltungen(student_uid, studiengang_kz, studiensemester_kurzbz, additional_lehrveranstaltung_id) {
return {
method: 'get',
url: 'api/frontend/v1/stv/projektarbeit/getLehrveranstaltungen',
params: { student_uid, studiengang_kz, studiensemester_kurzbz, additional_lehrveranstaltung_id }
};
},
getNoten() {
return {
method: 'get',
url: 'api/frontend/v1/stv/projektarbeit/getNoten'
};
},
loadProjektarbeit(projektarbeit_id) {
return {
method: 'get',
url: 'api/frontend/v1/stv/projektarbeit/loadProjektarbeit',
params: { projektarbeit_id }
};
},
addNewProjektarbeit(params) {
return {
method: 'post',
url: 'api/frontend/v1/stv/projektarbeit/insertProjektarbeit',
params
};
},
updateProjektarbeit(params) {
return {
method: 'post',
url: 'api/frontend/v1/stv/projektarbeit/updateProjektarbeit',
params
};
},
deleteProjektarbeit(projektarbeit_id) {
return {
method: 'post',
url: 'api/frontend/v1/stv/projektarbeit/deleteProjektarbeit',
params: { projektarbeit_id }
};
}
};
@@ -0,0 +1,24 @@
import Projektarbeit from './Projektarbeit/Projektarbeit.js';
export default {
name: "TabProjektarbeit",
components: {
Projektarbeit
},
provide() {
return {
config: this.config
};
},
props: {
modelValue: Object,
config: Object
},
data(){
return {}
},
template: `
<div class="stv-details-projektarbeit h-100 d-flex flex-column">
<projektarbeit ref="projektarbeit" :student="modelValue"></projektarbeit>
</div>`
};
@@ -0,0 +1,847 @@
import {CoreFilterCmpt} from "../../../../filter/Filter.js";
import FormForm from '../../../../Form/Form.js';
import FormInput from '../../../../Form/Input.js';
import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js";
import ApiStvAbschlusspruefung from '../../../../../api/factory/stv/abschlusspruefung.js';
export default {
components: {
CoreFilterCmpt,
BsModal,
FormForm,
FormInput,
PvAutoComplete,
AbschlusspruefungDropdown,
PruefungList
},
inject: {
cisRoot: {
from: 'cisRoot'
},
config: {
from: 'config',
required: true
},
$reloadList: {
from: '$reloadList',
required: true
},
isBerechtigtDocAndOdt: {
from: 'hasPermissionOutputformat',
default: false
}
},
computed: {
studentUids() {
if (this.student.uid)
{
return [this.student.uid];
}
return this.student.map(e => e.uid);
},
studentKzs(){
if (this.student.uid)
{
return [this.student.studiengang_kz];
}
return this.student.map(e => e.studiengang_kz);
},
stg_kz(){
return this.studentKzs[0];
},
},
props: {
student: Object
},
data() {
return {
tabulatorOptions: {
ajaxURL: 'dummy',
ajaxRequestFunc: () => this.$api.call(ApiStvAbschlusspruefung.getAbschlusspruefung(this.student.uid)),
ajaxResponse: (url, params, response) => response.data,
columns: [
{title: "vorsitz", field: "vorsitz_nachname"},
{title: "abschlussbeurteilung", field: "beurteilung_bezeichnung"},
{title: "prueferIn1", field: "p1_nachname", visible: false},
{title: "prueferIn2", field: "p2_nachname", visible: false},
{title: "prueferIn3", field: "p3_nachname", visible: false},
{
title: "datum",
field: "datum",
formatter: function (cell) {
const dateStr = cell.getValue();
if (!dateStr) return "";
const date = new Date(dateStr);
return date.toLocaleString("de-DE", {
day: "2-digit",
month: "2-digit",
year: "numeric",
hour12: false
});
}
},
{title: "uhrzeit", field: "uhrzeit"},
{
title: "freigabe",
field: "freigabedatum",
formatter: function (cell) {
const dateStr = cell.getValue();
if (!dateStr) return "";
const date = new Date(dateStr);
return date.toLocaleString("de-DE", {
day: "2-digit",
month: "2-digit",
year: "numeric",
hour12: false
});
}
},
{title: "pruefungsantritt", field: "antritt_bezeichnung"},
{
title: "sponsion",
field: "sponsion",
formatter: function (cell) {
const dateStr = cell.getValue();
if (!dateStr) return "";
const date = new Date(dateStr);
return date.toLocaleString("de-DE", {
day: "2-digit",
month: "2-digit",
year: "numeric",
hour12: false
});
}
},
{title: "anmerkung", field: "anmerkung"},
{title: "abschlusspruefung_id", field: "abschlusspruefung_id", visible: false},
{title: "typ", field: "pruefungstyp_kurzbz", visible: false},
{
title: 'Aktionen', field: 'actions',
minWidth: 150, // Ensures Action-buttons will be always fully displayed
formatter: (cell, formatterParams, onRendered) => {
let container = document.createElement('div');
container.className = "d-flex gap-2";
let button = document.createElement('button');
button.className = 'btn btn-outline-secondary btn-action';
button.innerHTML = '<i class="fa fa-edit"></i>';
button.title = this.$p.t('ui', 'bearbeiten');
button.addEventListener('click', (event) =>
this.actionEditAbschlusspruefung(cell.getData().abschlusspruefung_id)
);
container.append(button);
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.actionDeleteAbschlusspruefung(cell.getData().abschlusspruefung_id)
);
container.append(button);
container.append(cell.getData().actionDiv);
return container;
},
frozen: true
},
],
layout: 'fitDataFill',
layoutColumnsOnNewData: false,
height: 'auto',
minHeight: '200',
selectable: true,
index: 'abschlusspruefung_id',
persistenceID: 'stv-details-finalexam'
},
tabulatorEvents: [
{
event: 'dataLoaded',
handler: data => this.tabulatorData = data.map(item => {
item.actionDiv = document.createElement('div');
return item;
}),
},
{
event: 'tableBuilt',
handler: async() => {
await this.$p.loadCategory(['global', 'person', 'stv', 'abschlusspruefung', 'ui']);
let cm = this.$refs.table.tabulator.columnManager;
cm.getColumnByField('vorsitz_nachname').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'vorsitz_header')
});
cm.getColumnByField('beurteilung_bezeichnung').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'abschlussbeurteilung')
});
cm.getColumnByField('p1_nachname').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'pruefer1')
});
cm.getColumnByField('p2_nachname').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'pruefer2')
});
cm.getColumnByField('p3_nachname').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'pruefer3')
});
cm.getColumnByField('datum').component.updateDefinition({
title: this.$p.t('global', 'datum')
});
cm.getColumnByField('uhrzeit').component.updateDefinition({
title: this.$p.t('global', 'uhrzeit')
});
cm.getColumnByField('freigabedatum').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'freigabe')
});
cm.getColumnByField('antritt_bezeichnung').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'pruefungsantritt')
});
cm.getColumnByField('sponsion').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'sponsion')
});
cm.getColumnByField('anmerkung').component.updateDefinition({
title: this.$p.t('global', 'anmerkung')
});
cm.getColumnByField('pruefungstyp_kurzbz').component.updateDefinition({
title: this.$p.t('global', 'typ')
});
cm.getColumnByField('abschlusspruefung_id').component.updateDefinition({
title: this.$p.t('ui', 'abschlusspruefung_id')
});
/*
cm.getColumnByField('actions').component.updateDefinition({
title: this.$p.t('global', 'aktionen')
});
*/
}
}
],
tabulatorData: [],
lastSelected: null,
formData: {
typStg: null,
pruefungstyp_kurzbz: null,
akadgrad_id: null,
vorsitz: null,
pruefungsantritt_kurzbz: null,
abschlussbeurteilung_kurzbz: null,
datum: null,
sponsion: null,
pruefer1: null,
pruefer2: null,
pruefer3: null,
anmerkung: null,
protokoll: null,
note: null,
link: null
},
statusNew: true,
arrTypen: [],
arrAntritte: [],
arrBeurteilungen: [],
arrAkadGrad: [],
arrNoten: [],
filteredMitarbeiter: [],
filteredPruefer: [],
abortController: {
mitarbeiter: null,
pruefer: null
},
stgInfo: { typ: '', oe_kurzbz: '' }
}
},
watch: {
student(){
if (this.$refs.table) {
this.$refs.table.reloadTable();
}
this.getStudiengangByKz();
}
},
methods: {
getStudiengangByKz(){
this.stgInfo = { typ: '', oe_kurzbz: '' };
this.$api
.call(ApiStudiengang.getStudiengangByKz(this.stg_kz))
.then(result => this.stgInfo = result.data)
.catch(this.$fhcAlert.handleSystemError);
},
actionNewAbschlusspruefung() {
this.resetForm();
this.statusNew = true;
this.$refs.finalexamModal.show();
this.setDefaultFormData();
},
actionEditAbschlusspruefung(abschlusspruefung_id) {
this.resetForm();
this.statusNew = false;
this.$refs.finalexamModal.show();
this.loadAbschlusspruefung(abschlusspruefung_id);
},
actionDeleteAbschlusspruefung(abschlusspruefung_id) {
this.$fhcAlert
.confirmDelete()
.then(result => result
? abschlusspruefung_id
: Promise.reject({handled: true}))
.then(this.deleteAbschlusspruefung)
.catch(this.$fhcAlert.handleSystemError);
},
addNewAbschlusspruefung() {
const dataToSend = {
uid: this.student.uid,
formData: this.formData
};
return this.$refs.formFinalExam
.call(ApiStvAbschlusspruefung.addNewAbschlusspruefung(dataToSend))
.then(response => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
this.hideModal('finalexamModal');
this.resetForm();
})
.catch(this.$fhcAlert.handleSystemError)
.finally(() => {
this.reload();
});
},
hideModal(modalRef){
this.$refs[modalRef].hide();
},
reload() {
this.$refs.table.reloadTable();
},
loadAbschlusspruefung(abschlusspruefung_id) {
return this.$api
.call(ApiStvAbschlusspruefung.loadAbschlusspruefung(abschlusspruefung_id))
.then(result => {
this.formData = result.data;
//TODO(Manu) check if cisRoot is okay
this.formData.link = this.cisRoot + 'index.ci.php/lehre/Pruefungsprotokoll/showProtokoll?abschlusspruefung_id=' + this.formData.abschlusspruefung_id + '&fhc_controller_id=67481e5ed5490';
return result;
})
.catch(this.$fhcAlert.handleSystemError);
},
updateAbschlusspruefung(abschlusspruefung_id) {
const dataToSend = {
id: abschlusspruefung_id,
formData: this.formData
};
return this.$refs.formFinalExam
.call(ApiStvAbschlusspruefung.updateAbschlusspruefung(dataToSend))
.then(response => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
this.hideModal('finalexamModal');
this.resetForm();
})
.catch(this.$fhcAlert.handleSystemError)
.finally(() => {
this.reload();
});
},
deleteAbschlusspruefung(abschlusspruefung_id) {
return this.$api
.call(ApiStvAbschlusspruefung.deleteAbschlusspruefung(abschlusspruefung_id))
.then(response => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
})
.catch(this.$fhcAlert.handleSystemError)
.finally(() => {
this.reload();
});
},
resetForm() {
this.formData.pruefungstyp_kurzbz = null;
this.formData.akadgrad_id = null;
this.formData.vorsitz = null;
this.formData.pruefungsantritt_kurzbz = null;
this.formData.abschlussbeurteilung_kurzbz = null;
this.formData.datum = null; //oder new Date();
this.formData.sponsion = null;
this.formData.pruefer1 = null;
this.formData.pruefer2 = null;
this.formData.pruefer3 = null;
this.formData.anmerkung = null;
this.formData.protokoll = null;
this.formData.note = null;
this.formData.p1 = null;
this.formData.p2 = null;
this.formData.p3 = null;
this.formData.pv = null;
},
search(event) {
if (this.abortController.mitarbeiter) {
this.abortController.mitarbeiter.abort();
}
this.abortController.mitarbeiter = new AbortController();
return this.$api
.call(ApiStvAbschlusspruefung.getMitarbeiter(event.query))
.then(result => {
this.filteredMitarbeiter = result.data.retval;
});
},
searchNotAkad(event) {
if (this.abortController.pruefer) {
this.abortController.pruefer.abort();
}
this.abortController.pruefer = new AbortController();
return this.$api
.call(ApiStvAbschlusspruefung.getPruefer(event.query))
.then(result => {
this.filteredPruefer = result.data.retval;
});
},
setDefaultFormData() {
this.resetForm();
if (this.stgInfo.typ === 'b') {
this.formData.pruefungstyp_kurzbz = 'Bachelor';
this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster');
}
if (this.stgInfo.typ === 'd' || this.stgInfo === 'm') {
this.formData.pruefungstyp_kurzbz = 'Diplom';
this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster');
}
if (this.stgInfo.typ === 'lg') {
this.formData.pruefungstyp_kurzbz = 'lgabschluss';
}
if (!this.formData.akadgrad_id && this.arrAkadGrad.length > 0) {
this.formData.akadgrad_id = this.arrAkadGrad[0].akadgrad_id;
}
},
printDocument(link) {
window.open(link, '_blank');
},
},
created() {
this.$api
.call(ApiStvAbschlusspruefung.getTypenAbschlusspruefung())
.then(result => {
this.arrTypen = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$api
.call(ApiStvAbschlusspruefung.getTypenAntritte())
.then(result => {
this.arrAntritte = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$api
.call(ApiStvAbschlusspruefung.getBeurteilungen())
.then(result => {
this.arrBeurteilungen = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$api
.call(ApiStvAbschlusspruefung.getNoten())
.then(result => {
this.arrNoten = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$api
.call(ApiStvAbschlusspruefung.getAkadGrade(this.student.studiengang_kz))
.then(result => {
this.arrAkadGrad = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
if (!this.student.length) {
this.$api
.call(ApiStudiengang.getStudiengangByKz(this.student.studiengang_kz))
.then(result => {
this.stgInfo = result.data;
this.setDefaultFormData();
})
.catch(this.$fhcAlert.handleSystemError);
} else
this.getStudiengangByKz();
},
template: `
<div class="stv-details-abschlusspruefung h-100 pb-3">
<h4>{{this.$p.t('stv','tab_finalexam')}}</h4>
<div v-if="this.student.length">
<abschlusspruefung-dropdown
:showAllFormats="isBerechtigtDocAndOdt"
:studentUids="studentUids"
:showDropDownMulti="true"
:stgTyp="stgInfo.typ"
:stgKz="stg_kz"
:cisRoot="cisRoot"
@linkGenerated="printDocument"
></abschlusspruefung-dropdown>
</div>
<core-filter-cmpt
v-if="!this.student.length"
ref="table"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
table-only
:side-menu="false"
reload
new-btn-show
:new-btn-label="this.$p.t('stv', 'tab_finalexam')"
@click:new="actionNewAbschlusspruefung"
>
</core-filter-cmpt>
<!--Modal: finalexamModal-->
<bs-modal ref="finalexamModal" dialog-class="modal-xl modal-dialog-scrollable">
<template #title>
<p v-if="statusNew" class="fw-bold mt-3">{{$p.t('abschlusspruefung', 'abschluessPruefungAnlegen')}}</p>
<p v-else class="fw-bold mt-3">{{$p.t('abschlusspruefung', 'abschluessPruefungBearbeiten')}}</p>
</template>
<pruefung-list ref="pruefungList" :uid="student.uid"></pruefung-list>
<form-form v-if="!this.student.length" ref="formFinalExam" @submit.prevent>
<legend>{{this.$p.t('global','details')}}</legend>
<p v-if="statusNew">[{{$p.t('ui', 'neu')}}]</p>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-abschlusspruefung-typ"
:label="$p.t('global', 'typ')"
type="select"
v-model="formData.pruefungstyp_kurzbz"
name="pruefungstyp_kurzbz"
>
<option
v-for="typ in arrTypen"
:key="typ.pruefungstyp_kurzbz"
:value="typ.pruefungstyp_kurzbz"
>
{{typ.beschreibung}}
</option>
</form-input>
<form-input
container-class="col-6 stv-details-abschlusspruefung-note"
:label="$p.t('abschlusspruefung', 'notekommpruefung')"
type="select"
v-model="formData.note"
name="note"
>
<option :value="null"> -- {{$p.t('fehlermonitoring', 'keineAuswahl')}} -- </option>
<option
v-for="note in arrNoten"
:key="note.note"
:value="note.note"
>
{{note.bezeichnung}}
</option>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-abschlusspruefung-pruefungsantritt"
:label="$p.t('abschlusspruefung', 'pruefungsantritt')"
type="select"
v-model="formData.pruefungsantritt_kurzbz"
name="pruefungsantritt_kurzbz"
>
<option :value="null"> -- {{$p.t('fehlermonitoring', 'keineAuswahl')}} -- </option>
<option
v-for="antritt in arrAntritte"
:key="antritt.pruefungsantritt_kurzbz"
:value="antritt.pruefungsantritt_kurzbz"
>
{{antritt.bezeichnung}}
</option>
</form-input>
</div>
<div class="row mb-3">
<template v-if="statusNew">
<form-input
container-class="col-6 stv-details-abschlusspruefung-vorsitz"
:label="$p.t('abschlusspruefung', 'vorsitz_header')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.vorsitz"
name="vorsitz"
:suggestions="filteredMitarbeiter"
@complete="search"
:min-length="3"
>
</form-input>
</template>
<template v-else >
<form-input
v-if= "formData.pv"
container-class="col-6 stv-details-abschlusspruefung-vorsitz"
type="text"
name="name"
:label="$p.t('abschlusspruefung', 'vorsitz_header')"
v-model="formData.pv"
>
</form-input>
<form-input
v-else
container-class="col-6 stv-details-abschlusspruefung-vorsitz"
:label="$p.t('abschlusspruefung', 'vorsitz_header')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.vorsitz"
name="vorsitz"
:suggestions="filteredMitarbeiter"
@complete="search"
:min-length="3"
>
</form-input>
</template>
<template v-if="statusNew">
<form-input
container-class="col-6 stv-details-abschlusspruefung-pruefer1"
:label="$p.t('abschlusspruefung', 'pruefer1')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.pruefer1"
name="pruefer1"
:suggestions="filteredPruefer"
@complete="searchNotAkad"
:min-length="3"
>
</form-input>
</template>
<template v-else >
<form-input
v-if= "formData.p1"
container-class="col-6 stv-details-abschlusspruefung-pruefer1"
type="text"
name="name"
:label="$p.t('abschlusspruefung', 'pruefer1')"
v-model="formData.p1"
>
</form-input>
<form-input
v-else
container-class="col-6 stv-details-abschlusspruefung-pruefer1"
:label="$p.t('abschlusspruefung', 'pruefer1')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.pruefer1"
name="pruefer1"
:suggestions="filteredPruefer"
@complete="searchNotAkad"
:min-length="3"
>
</form-input>
</template>
</div>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-abschlusspruefung-abschlussbeurteilung_kurzbz"
:label="$p.t('abschlusspruefung', 'abschlussbeurteilung')"
type="select"
v-model="formData.abschlussbeurteilung_kurzbz"
name="abschlussbeurteilung_kurzbz"
>
<option :value="null"> -- {{$p.t('fehlermonitoring', 'keineAuswahl')}} -- </option>
<option
v-for="beurteilung in arrBeurteilungen"
:key="beurteilung.abschlussbeurteilung_kurzbz"
:value="beurteilung.abschlussbeurteilung_kurzbz"
>
{{beurteilung.bezeichnung}}
</option>
</form-input>
<template v-if="statusNew">
<form-input
container-class="col-6 stv-details-abschlusspruefung-pruefer2"
:label="$p.t('abschlusspruefung', 'pruefer2')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.pruefer2"
name="pruefer2"
:suggestions="filteredPruefer"
@complete="searchNotAkad"
:min-length="3"
>
</form-input>
</template>
<template v-else >
<form-input
v-if= "formData.p2"
container-class="col-6 stv-details-abschlusspruefung-pruefer2"
type="text"
name="name"
:label="$p.t('abschlusspruefung', 'pruefer2')"
v-model="formData.p2"
>
</form-input>
<form-input
v-else
container-class="col-6 stv-details-abschlusspruefung-pruefer2"
:label="$p.t('abschlusspruefung', 'pruefer2')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.pruefer2"
name="pruefer2"
:suggestions="filteredPruefer"
@complete="searchNotAkad"
:min-length="3"
>
</form-input>
</template>
</div>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-abschlusspruefung-akadgrad"
:label="$p.t('abschlusspruefung', 'akadGrad')"
type="select"
v-model="formData.akadgrad_id"
name="akadgrad_id"
>
<option
v-for="grad in arrAkadGrad"
:key="grad.akadgrad_id"
:value="grad.akadgrad_id"
>
{{grad.titel}}
</option>
</form-input>
<template v-if="statusNew">
<form-input
container-class="col-6 stv-details-abschlusspruefung-pruefer3"
:label="$p.t('abschlusspruefung', 'pruefer3')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.pruefer3"
name="pruefer3"
:suggestions="filteredPruefer"
@complete="searchNotAkad"
:min-length="3"
>
</form-input>
</template>
<template v-else >
<form-input
v-if= "formData.p3"
container-class="col-6 stv-details-abschlusspruefung-pruefer3"
type="text"
name="name"
:label="$p.t('abschlusspruefung', 'pruefer3')"
v-model="formData.p3"
>
</form-input>
<form-input
v-else
container-class="col-6 stv-details-abschlusspruefung-pruefer3"
:label="$p.t('abschlusspruefung', 'pruefer3')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.pruefer3"
name="pruefer3"
:suggestions="filteredPruefer"
@complete="searchNotAkad"
:min-length="3"
>
</form-input>
</template>
</div>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-abschlusspruefung-datum"
:label="$p.t('global', 'datum')"
type="DatePicker"
v-model="formData.datum"
auto-apply
:enable-time-picker="false"
format="dd.MM.yyyy"
name="datum"
:teleport="true"
>
</form-input>
<form-input
container-class="col-6 stv-details-abschlusspruefung-anmerkung"
:label="$p.t('global', 'anmerkung')"
type="textarea"
v-model="formData.anmerkung"
name="anmerkung"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-abschlusspruefung-sponsion"
:label="$p.t('abschlusspruefung', 'sponsion')"
type="DatePicker"
v-model="formData.sponsion"
auto-apply
:enable-time-picker="false"
format="dd.MM.yyyy"
name="sponsion"
:teleport="true"
>
</form-input>
<form-input
container-class="col-6 stv-details-abschlusspruefung-protokoll"
:label="$p.t('abschlusspruefung', 'protokoll')"
type="textarea"
v-model="formData.protokoll"
name="protokoll"
:rows= 10
>
</form-input>
</div>
<div class="row mb-3 col-6">
<div class="col">
<p >{{$p.t('abschlusspruefung', 'zurBeurteilung')}}</p>
</div>
<div class="col">
<p>
<a :href="formData.link" target="_blank" rel="noopener noreferrer">
{{$p.t('abschlusspruefung', 'pruefungsprotokoll')}}
</a>
</p>
</div>
</div>
</form-form>
<template #footer>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{$p.t('ui', 'abbrechen')}}</button>
<button v-if="statusNew" class="btn btn-primary" @click="addNewAbschlusspruefung()"> {{$p.t('ui', 'speichern')}}</button>
<button v-else class="btn btn-primary" @click="updateAbschlusspruefung(formData.abschlusspruefung_id)"> {{$p.t('ui', 'speichern')}}</button>
</template>
</bs-modal>
<Teleport v-for="data in tabulatorData" :key="data.abschlusspruefung_id" :to="data.actionDiv">
<abschlusspruefung-dropdown
:showAllFormats="isBerechtigtDocAndOdt"
:showDropDownMulti="false"
:abschlusspruefung_id="data.abschlusspruefung_id"
:studentUids="data.student_uid"
:stgPrfgTyp="data.pruefungstyp_kurzbz"
:stgKz="stg_kz"
:cisRoot="cisRoot"
@linkGenerated="printDocument"
></abschlusspruefung-dropdown>
</Teleport>
</div>
`
}
@@ -0,0 +1,461 @@
import {CoreFilterCmpt} from "../../../../filter/Filter.js";
import FormForm from '../../../../Form/Form.js';
import FormInput from '../../../../Form/Input.js';
import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js";
import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js';
export default {
components: {
CoreFilterCmpt,
FormForm,
FormInput,
PvAutoComplete
},
emits: ['details-saved'],
inject: {
defaultSemester: {
from: 'defaultSemester'
}
//~ cisRoot: {
//~ from: 'cisRoot'
//~ },
//~ config: {
//~ from: 'config',
//~ required: true
//~ }
},
computed: {
arrLes() {
let lehreinheiten = [];
if (this.formData.lehrveranstaltung_id) {
let lv = this.arrLvs.find(lv => {return lv.lehrveranstaltung_id == this.formData.lehrveranstaltung_id});
if (lv) lehreinheiten = lv.lehreinheiten
}
for (let le of lehreinheiten)
{
let bezeichnung = le.lehrfach_kurzbz + '-' + le.lehrform_kurzbz + ' ' + le.lehrfach_bezeichnung + ' ';
for (let grp of le.lehreinheitgruppen)
{
bezeichnung += grp.gruppe_kurzbz ? grp.gruppe_kurzbz : '' + grp.semester ?? '' + grp.verband ?? '' + grp.gruppe ?? '';
}
bezeichnung += ' (' + le.lektoren.join(' ') + ') ID: ' + le.lehreinheit_id;
le.bezeichnung = bezeichnung;
}
return lehreinheiten;
},
//~ preparedFormData() {
//~ console.log("FOR DATA CALLEd");
//~ if (this.formData.projektarbeit_id == null) delete(this.formData.projektarbeit_id);
//~ if (this.formData.firma) this.formData.firma_id = this.formData.firma.firma_id;
//~ delete(this.formData.firma);
//~ delete(this.formData.firma_name);
//~ delete(this.formData.lehrveranstaltung_id);
//~ // convert null value fields from string to null
//~ return this.formData;
//~ }
},
props: {
statusNew: Boolean,
student: Object,
projektarbeit: Object,
stg_kz: Number
},
data() {
return {
formData: {
projektarbeit_id: null,
titel: null,
titel_english: null,
themenbereich: null,
projekttyp_kurzbz: null,
firma: null,
lehrveranstaltung_id: null,
lehreinheit_id: null,
beginn: null,
ende: null,
freigegeben: true,
gesperrtbis: null,
note: null,
final: true,
anmerkung: null
},
arrTypen: [],
arrFirmen: [],
arrLvs: [],
arrNoten: [],
filteredFirmen: [],
abortController: {
firma: null
}
}
},
methods: {
resetForm() {
this.formData.projektarbeit_id = null;
this.formData.titel = null;
this.formData.titel_english = null;
this.formData.themenbereich = null;
this.formData.projekttyp_kurzbz = null;
this.formData.firma = null;
this.formData.lehrveranstaltung_id = null;
this.formData.lehreinheit_id = null;
this.formData.beginn = null;
this.formData.ende = null;
this.formData.freigegeben = true;
this.formData.gesperrtbis = null;
this.formData.note = null;
this.formData.final = true;
this.formData.anmerkung = null;
},
getFormData(statusNew, studiensemester_kurzbz, additional_lehrveranstaltung_id/*, successCallback*/) {
//~ let callArray = [
//~ this.$api.call(ApiStvProjektarbeit.getTypenProjektarbeit()),
//~ this.$api.call(ApiStvProjektarbeit.getLehrveranstaltungen(
//~ this.student.uid,
//~ projektarbeit_id ? null : this.student.studiengang_kz,
//~ studiensemester_kurzbz ?? this.defaultSemester,
//~ additional_lehrveranstaltung_id ?? null
//~ )),
//~ this.$api.call(ApiStvProjektarbeit.getNoten())
//~ ];
//~ if (projektarbeit_id) callArray.push(this.$api.call(ApiStvProjektarbeit.loadProjektarbeit(projektarbeit_id)));
//~ // Run when All promises are settled
//~ Promise.allSettled(callArray).then((results) => {
//~ let hasError = false;
//~ let allFormData = [];
//~ results.forEach((promise_result) => {
//~ if (promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success") {
//~ allFormData.push(promise_result.value.data);
//~ } else {
//~ hasError = true;
//~ //this.$fhcAlert.handleSystemError(promise_result);
//~ }
//~ //let data = promise_result.value.data;
//~ console.log(promise_result.status);
//~ });
//~ if (!hasError) {
//~ this.setFormData(allFormData[0], allFormData[1], allFormData[2], allFormData[3], allFormData[4] ?? null);
//~ if (successCallback) successCallback();
//~ }
//~ });
this.$api
.call(ApiStvProjektarbeit.getTypenProjektarbeit())
.then(result => {
this.arrTypen = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$api
.call(ApiStvProjektarbeit.getLehrveranstaltungen(
this.student.uid,
statusNew ? this.student.studiengang_kz : null,
studiensemester_kurzbz ?? this.defaultSemester,
additional_lehrveranstaltung_id
))
.then(result => {
this.arrLvs = result.data
}
)
.catch(this.$fhcAlert.handleSystemError);
this.$api
.call(ApiStvProjektarbeit.getNoten())
.then(result => {
this.arrNoten = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
},
setFormData(arrTypen, arrLvs, arrNoten, projektarbeitData) {
this.arrTypen = arrTypen;
this.arrLvs = arrLvs;
this.arrNoten = arrNoten;
if (projektarbeitData) {
projektarbeitData.firma = {firma_id: projektarbeitData.firma_id, name: projektarbeitData.firma_name};
this.formData = projektarbeitData;
}
},
loadProjektarbeit(projektarbeit_id) {
return this.$api
.call(ApiStvProjektarbeit.loadProjektarbeit(projektarbeit_id))
.then(result => {
this.formData = result.data;
return result;
})
.catch(this.$fhcAlert.handleSystemError)
},
addNewProjektarbeit() {
let dataToSend = {
uid: this.student.uid,
formData: this.getPreparedFormData()
};
return this.$refs.formDetails
.call(ApiStvProjektarbeit.addNewProjektarbeit(dataToSend));
},
updateProjektarbeit() {
let dataToSend = {
projektarbeit_id: this.formData.projektarbeit_id,
formData: this.getPreparedFormData()
};
return this.$refs.formDetails
.call(ApiStvProjektarbeit.updateProjektarbeit(dataToSend));
},
searchFirma(event) {
if (this.abortController.firma) {
this.abortController.firma.abort();
}
this.abortController.firma = new AbortController();
return this.$api
.call(ApiStvProjektarbeit.getFirmen(event.query))
.then(result => {
this.filteredFirmen = result.data;
});
},
lvChanged(event) {
this.formData.lehreinheit_id = null;
},
getPreparedFormData() {
let preparedFormData = JSON.parse(JSON.stringify(this.formData)); // deep copy
// delete "helper" fields
if (preparedFormData.projektarbeit_id == null) delete(preparedFormData.projektarbeit_id);
if (preparedFormData.firma) preparedFormData.firma_id = preparedFormData.firma.firma_id;
delete(preparedFormData.firma);
delete(preparedFormData.firma_name);
delete(preparedFormData.lehrveranstaltung_id);
return preparedFormData;
}
//~ setDefaultFormData() {
//~ this.resetForm();
//~ },
},
template: `
<form-form v-if="!this.student.length" ref="formDetails" @submit.prevent>
<legend>{{this.$p.t('global','details')}}</legend>
<p v-if="statusNew">[{{$p.t('ui', 'neu')}}]</p>
<div class="row mb-3">
<form-input
container-class="stv-details-projektarbeit-titel"
type="text"
name="titel"
:label="$p.t('projektarbeit', 'titel')"
v-model="formData.titel"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="stv-details-projektarbeit-titel_english"
type="text"
name="titel_english"
:label="$p.t('projektarbeit', 'titelEnglisch')"
v-model="formData.titel_english"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="stv-details-projektarbeit-themenbereich"
type="text"
name="themenbereich"
:label="$p.t('projektarbeit', 'themenbereich')"
v-model="formData.themenbereich"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="stv-details-projektarbeit-typ"
:label="$p.t('global', 'typ')"
type="select"
v-model="formData.projekttyp_kurzbz"
name="projekttyp_kurzbz"
>
<option
v-for="typ in arrTypen"
:key="typ.projekttyp_kurzbz"
:value="typ.projekttyp_kurzbz"
>
{{typ.bezeichnung}}
</option>
</form-input>
</div>
<div class="row mb-3">
<!-- <form-input
v-if= "formData.firma_name"
container-class="col-6 stv-details-projektarbeit-firma"
type="text"
name="name"
:label="$p.t('projektarbeit', 'firma')"
v-model="formData.firma_name"
>
</form-input> -->
<form-input
container-class="stv-details-projektarbeit-firma"
:label="$p.t('projektarbeit', 'firma')"
type="autocomplete"
optionLabel="name"
v-model="formData.firma"
name="firma"
:suggestions="filteredFirmen"
@complete="searchFirma"
:min-length="3"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="stv-details-projektarbeit-lv"
:label="$p.t('projektarbeit', 'lehrveranstaltung')"
type="select"
v-model="formData.lehrveranstaltung_id"
name="lehrveranstaltung_id"
@change="lvChanged($event)"
>
<option :value="null"> -- {{$p.t('fehlermonitoring', 'keineAuswahl')}} -- </option>
<option
v-for="lv in arrLvs"
:key="lv.lehrveranstaltung_id"
:value="lv.lehrveranstaltung_id"
>
{{lv.bezeichnung + ' ' + lv.orgform_kurzbz + ' (' + lv.semester + ' Sem) ID: ' + lv.lehrveranstaltung_id}}
</option>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="stv-details-projektarbeit-le"
:label="$p.t('global', 'lvTeil')"
type="select"
v-model="formData.lehreinheit_id"
name="lehreinheit_id"
>
<option :value="null"> -- {{$p.t('fehlermonitoring', 'keineAuswahl')}} -- </option>
<option
v-for="le in arrLes"
:key="le.lehreinheit_id"
:value="le.lehreinheit_id"
>
{{le.bezeichnung}}
</option>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-projektarbeit-beginn"
:label="$p.t('projektarbeit', 'beginn')"
type="DatePicker"
v-model="formData.beginn"
auto-apply
:enable-time-picker="false"
format="dd.MM.yyyy"
name="beginn"
>
</form-input>
<form-input
container-class="col-6 stv-details-projektarbeit-ende"
:label="$p.t('projektarbeit', 'ende')"
type="DatePicker"
v-model="formData.ende"
auto-apply
:enable-time-picker="false"
format="dd.MM.yyyy"
name="ende"
>
</form-input>
</div>
<div class="row mb-3 align-items-center">
<form-input
container-class="col-8 stv-details-projektarbeit-gesperrtbis"
:label="$p.t('projektarbeit', 'gesperrtbis')"
type="DatePicker"
v-model="formData.gesperrtbis"
auto-apply
:enable-time-picker="false"
format="dd.MM.yyyy"
name="gesperrtbis"
>
</form-input>
<div class="col-4">
<form-input
container-class="form-check stv-details-projektarbeit-freigegeben"
type="checkbox"
name="freigegeben"
:label="$p.t('projektarbeit','freigegeben')"
v-model="formData.freigegeben"
>
</form-input>
</div>
</div>
<div class="row mb-3 align-items-center">
<form-input
container-class="col-8 stv-details-projektarbeit-note"
:label="$p.t('projektarbeit', 'note')"
type="select"
v-model="formData.note"
name="note"
>
<option :value="null"> -- {{$p.t('fehlermonitoring', 'keineAuswahl')}} -- </option>
<option
v-for="note in arrNoten"
:key="note.note"
:value="note.note"
>
{{note.bezeichnung}}
</option>
</form-input>
<div class="col-4">
<form-input
container-class="form-check stv-details-projektarbeit-final"
type="checkbox"
name="final"
:label="$p.t('projektarbeit','final')"
v-model="formData.final"
>
</form-input>
</div>
</div>
<div class="row mb-3">
<form-input
container-class="col-12 stv-details-abschlusspruefung-anmerkung"
:label="$p.t('projektarbeit', 'anmerkung')"
type="textarea"
v-model="formData.anmerkung"
name="anmerkung"
:rows= 3
>
</form-input>
</div>
</form-form>`
}
@@ -0,0 +1,377 @@
import {CoreFilterCmpt} from "../../../../filter/Filter.js";
import BsModal from "../../../../Bootstrap/Modal.js";
import FormForm from '../../../../Form/Form.js';
import FormInput from '../../../../Form/Input.js';
import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js";
import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js';
import ProjektarbeitDetails from "./Details.js";
export default {
components: {
CoreFilterCmpt,
BsModal,
FormForm,
FormInput,
PvAutoComplete,
ProjektarbeitDetails
},
inject: {
cisRoot: {
from: 'cisRoot'
},
config: {
from: 'config',
required: true
},
$reloadList: {
from: '$reloadList',
required: true
},
isBerechtigtDocAndOdt: {
from: 'hasPermissionOutputformat',
default: false
}
},
computed: {
//~ studentUids() {
//~ if (this.student.uid)
//~ {
//~ return [this.student.uid];
//~ }
//~ return this.student.map(e => e.uid);
//~ },
studentKzs(){
if (this.student.uid)
{
return [this.student.studiengang_kz];
}
return this.student.map(e => e.studiengang_kz);
},
stg_kz(){
return this.studentKzs.length > 0 ? this.studentKzs.length[0] : null;
}
},
props: {
student: Object
},
data() {
return {
tabulatorOptions: {
ajaxURL: 'dummy',
ajaxRequestFunc: () => this.$api.call(ApiStvProjektarbeit.getProjektarbeit(this.student.uid)),
ajaxResponse: (url, params, response) => response.data,
columns: [
{title: "Projektarbeit ID", field: "projektarbeit_id", visible: false},
{title: "Typ", field: "projekttyp_kurzbz"},
{title: "Studiensemester", field: "studiensemester_kurzbz"},
{title: "Titel", field: "titel"},
{
title: "Abgabe Enduplad",
field: "abgabedatum",
formatter: function (cell) {
const dateStr = cell.getValue();
if (!dateStr) return "";
const date = new Date(dateStr);
return date.toLocaleString("de-DE", {
day: "2-digit",
month: "2-digit",
year: "numeric",
hour12: false
});
}
},
{
title: "Beginn",
field: "beginn",
formatter: function (cell) {
const dateStr = cell.getValue();
if (!dateStr) return "";
const date = new Date(dateStr);
return date.toLocaleString("de-DE", {
day: "2-digit",
month: "2-digit",
year: "numeric",
hour12: false
});
},
visible: false
},
{
title: "Ende",
field: "ende",
formatter: function (cell) {
const dateStr = cell.getValue();
if (!dateStr) return "";
const date = new Date(dateStr);
return date.toLocaleString("de-DE", {
day: "2-digit",
month: "2-digit",
year: "numeric",
hour12: false
});
},
visible: false
},
{
title:"Freigegeben",
field:"freigegeben",
formatter:"tickCross",
hozAlign:"center",
formatterParams: {
tickElement: '<i class="fa fa-check text-success"></i>',
crossElement: '<i class="fa fa-xmark text-danger"></i>'
},
visible: false
},
{
title: "Gesperrt bis",
field: "gesperrtbis",
formatter: function (cell) {
const dateStr = cell.getValue();
if (!dateStr) return "";
const date = new Date(dateStr);
return date.toLocaleString("de-DE", {
day: "2-digit",
month: "2-digit",
year: "numeric",
hour12: false
});
},
visible: false
},
{title: "Themenbereich", field: "themenbereich", visible: false},
{title: "Anmerkung", field: "anmerkung", visible: false},
{title: "Lehreinheit ID", field: "lehreinheit_id", visible: false},
{title: "Student UID", field: "student_uid", visible: false},
{
title:"Final",
field:"final",
formatter:"tickCross",
hozAlign:"center",
formatterParams: {
tickElement: '<i class="fa fa-check text-success"></i>',
crossElement: '<i class="fa fa-xmark text-danger"></i>'
},
visible: false
},
{title: "Firma ID", field: "firma_id", visible: false},
{
title: 'Aktionen', field: 'actions',
minWidth: 150, // Ensures Action-buttons will be always fully displayed
formatter: (cell, formatterParams, onRendered) => {
let container = document.createElement('div');
container.className = "d-flex gap-2";
let button = document.createElement('button');
button.className = 'btn btn-outline-secondary btn-action';
button.innerHTML = '<i class="fa fa-edit"></i>';
button.title = this.$p.t('ui', 'bearbeiten');
button.addEventListener('click', (event) => {
let data = cell.getData();
this.actionEditProjektarbeit(data.projektarbeit_id, data.studiensemester_kurzbz, data.lehrveranstaltung_id);
});
container.append(button);
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.actionDeleteProjektarbeit(cell.getData().projektarbeit_id)
);
container.append(button);
container.append(cell.getData().actionDiv);
return container;
},
frozen: true
},
],
layout: 'fitDataFill',
layoutColumnsOnNewData: false,
height: 'auto',
minHeight: '200',
selectable: 1,
index: 'projektarbeit_id',
persistenceID: 'stv-details-projektarbeit'
},
tabulatorEvents: [
{
event: 'rowSelectionChanged',
handler: this.rowSelectionChanged
},
{
event: 'dataLoaded',
handler: data => this.tabulatorData = data.map(item => {
item.actionDiv = document.createElement('div');
return item;
}),
},
{
event: 'tableBuilt',
handler: async() => {
await this.$p.loadCategory(['global', 'person', 'stv', 'ui']);
let cm = this.$refs.table.tabulator.columnManager;
//~ cm.getColumnByField('vorsitz_nachname').component.updateDefinition({
//~ title: this.$p.t('abschlusspruefung', 'vorsitz_header')
//~ });
/*
cm.getColumnByField('actions').component.updateDefinition({
title: this.$p.t('global', 'aktionen')
});
*/
}
},
],
tabulatorData: [],
lastSelected: null,
statusNew: true,
studiensemester_kurzbz: null,
lehrveranstaltung_id: null
}
},
//~ watch: {
//~ student(){
//~ if (this.$refs.table) {
//~ this.$refs.table.reloadTable();
//~ }
//~ this.getStudiengangByKz();
//~ }
//~ },
methods: {
actionNewProjektarbeit() {
this.statusNew = true;
this.$refs.projektarbeitDetails.resetForm();
this.$refs.projektarbeitDetails.getFormData();
this.$refs.projektarbeitModal.show();
},
actionEditProjektarbeit(projektarbeit_id, studiensemester_kurzbz, lehrveranstaltung_id) {
this.statusNew = false;
this.$refs.projektarbeitDetails.getFormData(this.statusNew, studiensemester_kurzbz, lehrveranstaltung_id);
this.$refs.projektarbeitDetails.loadProjektarbeit(projektarbeit_id);
this.$refs.projektarbeitModal.show();
},
actionDeleteProjektarbeit(projektarbeit_id) {
this.$fhcAlert
.confirmDelete()
.then(result => result
? projektarbeit_id
: Promise.reject({handled: true}))
.then(this.deleteProjektarbeit)
.catch(this.$fhcAlert.handleSystemError);
},
addNewProjektarbeit() {
Promise.allSettled([
this.$refs.projektarbeitDetails.addNewProjektarbeit()
]).then((results) => {
let hasError = false;
results.forEach((promise_result) => {
if (!(promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success")) {
hasError = true;
}
});
if (!hasError) {
this.projektarbeitSaved();
}
});
},
updateProjektarbeit() {
Promise.allSettled(
[
this.$refs.projektarbeitDetails.updateProjektarbeit()
]).then((results) => {
let hasError = false;
results.forEach((promise_result) => {
if (!(promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success")) {
hasError = true;
}
});
if (!hasError) {
this.projektarbeitSaved();
}
});
},
deleteProjektarbeit(projektarbeit_id) {
return this.$api
.call(ApiStvProjektarbeit.deleteProjektarbeit(projektarbeit_id))
.then(response => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
})
.catch(this.$fhcAlert.handleSystemError)
.finally(() => {
this.reload();
});
},
projektarbeitSaved() {
this.reload();
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
this.hideModal('projektarbeitModal');
this.$refs.projektarbeitDetails.resetForm();
},
rowSelectionChanged(data) {
console.log("selection changed");
this.lastSelected = data.length > 0 ? data[0] : null;
},
hideModal(modalRef){
this.$refs[modalRef].hide();
},
reload() {
this.$refs.table.reloadTable();
}
},
created() {
},
template: `
<div class="stv-details-projektarbeit h-100 pb-3">
<h4>{{this.$p.t('stv','tab_projektarbeit')}}</h4>
<core-filter-cmpt
v-if="!this.student.length"
ref="table"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
table-only
:side-menu="false"
reload
new-btn-show
:new-btn-label="this.$p.t('stv', 'tab_projektarbeit')"
@click:new="actionNewProjektarbeit"
>
</core-filter-cmpt>
<!--Modal: projektarbeitModal-->
<bs-modal ref="projektarbeitModal" dialog-class="modal-xl modal-dialog-scrollable">
<template #title>
<p v-if="statusNew" class="fw-bold mt-3">{{$p.t('projektarbeit', 'projektarbeitAnlegen')}}</p>
<p v-else class="fw-bold mt-3">{{$p.t('projektarbeit', 'projektarbeitBearbeiten')}}</p>
</template>
<projektarbeit-details ref="projektarbeitDetails" :student="student" :stg_kz="stg_kz"></projektarbeit-details>
<template #footer>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{$p.t('ui', 'abbrechen')}}</button>
<button v-if="statusNew" class="btn btn-primary" @click="addNewProjektarbeit()"> {{$p.t('ui', 'speichern')}}</button>
<button v-else class="btn btn-primary" @click="updateProjektarbeit()"> {{$p.t('ui', 'speichern')}}</button>
</template>
</bs-modal>
</div>
`
}