mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-25 16:44:28 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e8e977eef | ||
|
|
94eb7021bb | ||
|
|
ef8314c33a | ||
|
|
e4ebdd59b6 | ||
|
|
d1cc7244f7 | ||
|
|
2f5b90b9d5 | ||
|
|
9b90e0edde | ||
|
|
56e9b253d2 | ||
|
|
c5c7123358 | ||
|
|
50e93fc9ba | ||
|
|
47ea1e848c | ||
|
|
e0f99a8e88 | ||
|
|
63aebde7f2 | ||
|
|
62f5b66324 | ||
|
|
ef08e39449 | ||
|
|
c720c46125 | ||
|
|
597d4dbfec | ||
|
|
d67cad925d | ||
|
|
2d9e9df8a0 | ||
|
|
6d6659f6e5 | ||
|
|
6512ad0f1c | ||
|
|
f034a99928 | ||
|
|
40ae57fb0c | ||
|
|
7e6805ca98 | ||
|
|
871534af52 | ||
|
|
4dd4d8aaa5 | ||
|
|
f9ac824cc0 | ||
|
|
db048e876c | ||
|
|
e6ef234c8b | ||
|
|
5a77478071 | ||
|
|
8280ec42b0 | ||
|
|
df639c8b07 | ||
|
|
48512f46ab | ||
|
|
8bab5285e9 | ||
|
|
76cdaefdc7 | ||
|
|
f725594f0c | ||
|
|
d8e57d43f9 | ||
|
|
5c9710f44d | ||
|
|
92030ca697 | ||
|
|
993dff3351 | ||
|
|
0a118a1427 | ||
|
|
4ab0c0a44e | ||
|
|
43281c6ba2 | ||
|
|
343964750b | ||
|
|
2aee86baba | ||
|
|
0d51df95f9 | ||
|
|
deebe987d3 | ||
|
|
cb77f3148a | ||
|
|
cb64c83b50 | ||
|
|
ed747fe07c | ||
|
|
10d58d1a42 | ||
|
|
fd2ff27e22 | ||
|
|
594333889d | ||
|
|
94e25da6c8 | ||
|
|
430da0b236 | ||
|
|
0df082af1f | ||
|
|
56bfe46675 | ||
|
|
daf9d2ea15 | ||
|
|
4b8af46a2e | ||
|
|
fd2de106f8 | ||
|
|
08182fe0f5 | ||
|
|
1e32bc211b | ||
|
|
5ee72fd836 |
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class Zeitsperren extends Auth_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'index' => ['basis/cis:r'],
|
||||
]);
|
||||
|
||||
// Load Libraries
|
||||
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* index loads the view Zeitsperren
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$viewData = array(
|
||||
'uid'=>getAuthUID(),
|
||||
);
|
||||
|
||||
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'zeitsperren']);
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ class Studium extends FHCAPI_Controller
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getStudienAllSemester'=> self::PERM_LOGGED,
|
||||
'getAllStudienSemester'=> self::PERM_LOGGED,
|
||||
'getStudiengaengeForStudienSemester'=> self::PERM_LOGGED,
|
||||
'getStudienplaeneBySemester'=> self::PERM_LOGGED,
|
||||
'getLvEvaluierungInfo'=> self::PERM_LOGGED,
|
||||
@@ -51,7 +51,7 @@ class Studium extends FHCAPI_Controller
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
public function getStudienAllSemester(){
|
||||
public function getAllStudienSemester(){
|
||||
|
||||
$parameter_studiensemester = $this->input->get('studiensemester',true);
|
||||
$parameter_studiengang = $this->input->get('studiengang',true);
|
||||
@@ -59,24 +59,26 @@ class Studium extends FHCAPI_Controller
|
||||
$parameter_studienplan = $this->input->get('studienplan',true);
|
||||
|
||||
$aktuelles_studiensemester = current($this->getDataOrTerminateWithError($this->StudiensemesterModel->getAktOrNextSemester()));
|
||||
|
||||
|
||||
if($this->getDataOrTerminateWithError($this->StudentModel->isStudent(getAuthUID()))){
|
||||
$studentLehrverband =$this->StudentlehrverbandModel->loadWhere(["student_uid" => getAuthUID(), "studiensemester_kurzbz" => $aktuelles_studiensemester->studiensemester_kurzbz]);
|
||||
$studentLehrverband = current($this->getDataOrTerminateWithError($studentLehrverband));
|
||||
$lv_result =$this->StudentlehrverbandModel->loadWhere([
|
||||
"student_uid" => getAuthUID(),
|
||||
"studiensemester_kurzbz" => $aktuelles_studiensemester->studiensemester_kurzbz
|
||||
]);
|
||||
$lv_data = $this->getDataOrTerminateWithError($lv_result);
|
||||
|
||||
if ($studentLehrverband = current($lv_data)) {
|
||||
$student_studiensemester = $studentLehrverband->studiensemester_kurzbz;
|
||||
$student_studiengang = $studentLehrverband->studiengang_kz;
|
||||
$student_semester = $studentLehrverband->semester;
|
||||
}
|
||||
|
||||
$student_studiensemester = $studentLehrverband->studiensemester_kurzbz;
|
||||
$student_studiengang = $studentLehrverband->studiengang_kz;
|
||||
$student_semester = $studentLehrverband->semester;
|
||||
$student_studienplan = $this->getStudienPlanFromPrestudentStatus(getAuthPersonId())->studienplan_id;
|
||||
|
||||
if(!isset($parameter_studiensemester))
|
||||
$parameter_studiensemester = $student_studiensemester;
|
||||
if(!isset($parameter_studiengang))
|
||||
$parameter_studiengang = $student_studiengang;
|
||||
if(!isset($parameter_semester))
|
||||
$parameter_semester = $student_semester;
|
||||
if(!isset($parameter_studienplan))
|
||||
$parameter_studienplan = $student_studienplan;
|
||||
|
||||
$parameter_studiensemester = $parameter_studiensemester ?? $student_studiensemester;
|
||||
$parameter_studiengang = $parameter_studiengang ?? $student_studiengang;
|
||||
$parameter_semester = $parameter_semester ?? $student_semester;
|
||||
$parameter_studienplan = $parameter_studienplan ?? $student_studienplan;
|
||||
}
|
||||
|
||||
if(isset($parameter_studiensemester)){
|
||||
|
||||
@@ -1,367 +0,0 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class Zeitsperren extends FHCAPI_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getZeitsperrenUser' => self::PERM_LOGGED,
|
||||
'getTypenZeitsperren' => self::PERM_LOGGED,
|
||||
'getTypenErreichbarkeit' => self::PERM_LOGGED,
|
||||
'getStunden' => self::PERM_LOGGED,
|
||||
'loadZeitsperre' => self::PERM_LOGGED,
|
||||
'add' => self::PERM_LOGGED,
|
||||
'update' => self::PERM_LOGGED,
|
||||
'delete' => self::PERM_LOGGED,
|
||||
]);
|
||||
|
||||
// Load Libraries
|
||||
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
|
||||
$this->load->library('form_validation');
|
||||
|
||||
// Load language phrases
|
||||
$this->loadPhrases([
|
||||
'ui',
|
||||
'person',
|
||||
'zeitsperren'
|
||||
]);
|
||||
|
||||
// Load models
|
||||
$this->load->model('ressource/Zeitsperre_model', 'ZeitsperreModel');
|
||||
$this->load->model('ressource/Zeitsperretyp_model', 'ZeitsperretypModel');
|
||||
$this->load->model('ressource/Erreichbarkeit_model', 'ErreichbarkeitModel');
|
||||
$this->load->model('ressource/Stunde_model', 'StundeModel');
|
||||
$this->load->model('ressource/Zeitaufzeichnung_model', 'ZeitaufzeichnungModel');
|
||||
}
|
||||
|
||||
public function getZeitsperrenUser($uid)
|
||||
{
|
||||
//check if $uid is passedUser
|
||||
$loggedInUser = getAuthUID();
|
||||
if($loggedInUser != $uid) {
|
||||
$this->load->library('PermissionLib');
|
||||
$isAdmin = $this->permissionlib->isBerechtigt('admin');
|
||||
if(!$isAdmin) {
|
||||
$this->terminateWithError($this->p->t('ui', 'noAdmin'), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
}
|
||||
|
||||
$result = $this->ZeitsperreModel->getZeitsperrenUser($uid);
|
||||
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
public function getTypenZeitsperren()
|
||||
{
|
||||
$this->ZeitsperretypModel->addOrder('beschreibung', 'ASC');
|
||||
$result = $this->ZeitsperretypModel->load();
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
public function getTypenErreichbarkeit()
|
||||
{
|
||||
$result = $this->ErreichbarkeitModel->load();
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
public function getStunden()
|
||||
{
|
||||
$this->StundeModel->addOrder('stunde', 'ASC');
|
||||
$result = $this->StundeModel->load();
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
public function loadZeitsperre($zeitsperre_id)
|
||||
{
|
||||
$this->ZeitsperreModel->addSelect(
|
||||
'campus.tbl_zeitsperre.*, typ.*,
|
||||
ma.person_id AS ma_person_id, ma.vorname AS ma_vorname, ma.nachname AS ma_nachname,
|
||||
ma.titelpre AS ma_titelpre, ma.titelpost AS ma_titelpost'
|
||||
);
|
||||
$this->ZeitsperreModel->addJoin('campus.tbl_zeitsperretyp typ', 'ON (typ.zeitsperretyp_kurzbz = campus.tbl_zeitsperre.zeitsperretyp_kurzbz)');
|
||||
$this->ZeitsperreModel->addJoin('public.tbl_benutzer ben', 'ON (ben.uid = campus.tbl_zeitsperre.vertretung_uid)', 'LEFT');
|
||||
$this->ZeitsperreModel->addJoin('public.tbl_person ma', 'ON (ma.person_id = ben.person_id)', 'LEFT');
|
||||
$result = $this->ZeitsperreModel->loadWhere(
|
||||
array('zeitsperre_id' => $zeitsperre_id)
|
||||
);
|
||||
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->terminateWithSuccess((current(getData($result)) ?: []));
|
||||
}
|
||||
|
||||
public function add($mitarbeiter_uid)
|
||||
{
|
||||
$loggedInUser = getAuthUID();
|
||||
|
||||
if($mitarbeiter_uid != $loggedInUser)
|
||||
$this->terminateWithError($this->p->t('ui', 'noPermission'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
$this->form_validation->set_rules('zeitsperretyp_kurzbz', 'Grund Zeitsperre', 'required', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Grund Zeitsperre'])
|
||||
]);
|
||||
|
||||
$this->form_validation->set_rules('vondatum', 'VonDatum', 'required|is_valid_date', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'VonDatum']),
|
||||
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VonDatum'])
|
||||
]);
|
||||
|
||||
$this->form_validation->set_rules('bisdatum', 'BisDatum', 'required|is_valid_date|callback_check_von_bis_datum|callback_check_diff_intval', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'BisDatum']),
|
||||
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'BisDatum']),
|
||||
'check_von_bis_datum' => $this->p->t('zeitsperre', 'error_VonDatumGroesserAlsBisDatum'),
|
||||
'check_diff_intval' => $this->p->t('zeitsperre', 'error_zeitraumAuffallendHoch')
|
||||
]);
|
||||
|
||||
if ($this->form_validation->run() == false)
|
||||
{
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
}
|
||||
|
||||
$bezeichnung = $this->input->post('bezeichnung');
|
||||
$vondatum = $this->input->post('vondatum');
|
||||
$vonstunde = $this->input->post('vonstunde');
|
||||
$bisdatum = $this->input->post('bisdatum');
|
||||
$bisstunde = $this->input->post('bisstunde');
|
||||
//$vonIso = $this->input->post('vonISO'); //Timestamp für Stunde
|
||||
//$bisIso = $this->input->post('bisISO'); //Timestamp für Stunde
|
||||
$erreichbarkeit_kurzbz = $this->input->post('erreichbarkeit_kurzbz');
|
||||
$vertretung_uid = $this->input->post('vertretung_uid');
|
||||
$zeitsperretyp_kurzbz = $this->input->post('zeitsperretyp_kurzbz');
|
||||
|
||||
//check if existing zeitsperre
|
||||
$result = $this->ZeitsperreModel->getSperreByDate($mitarbeiter_uid, $vondatum, $vonstunde, true);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
if(hasData($result))
|
||||
{
|
||||
$this->terminateWithError($this->p->t('zeitsperren', 'error_existingZeitsperre', ['typ'=> current($data)->zeitsperretyp_kurzbz]), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
//check if existing zeitaufzeichnung
|
||||
if(in_array($zeitsperretyp_kurzbz, Zeitsperre_model::BLOCKIERENDE_ZEITSPERREN))
|
||||
{
|
||||
$result = $this->ZeitsperreModel->existsZeitaufzeichnung($mitarbeiter_uid, $vondatum, $bisdatum);
|
||||
|
||||
if(hasData($result))
|
||||
$this->terminateWithError($this->p->t('zeitsperren', 'error_existingZeitaufzeichnung'), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
$result = $this->ZeitsperreModel->insert(
|
||||
[
|
||||
'mitarbeiter_uid' => $mitarbeiter_uid,
|
||||
'bezeichnung' => $bezeichnung,
|
||||
'vondatum' => $vondatum,
|
||||
'vonstunde' => $vonstunde,
|
||||
'bisdatum' => $bisdatum,
|
||||
'bisstunde' => $bisstunde,
|
||||
'erreichbarkeit_kurzbz' => $erreichbarkeit_kurzbz,
|
||||
'zeitsperretyp_kurzbz' => $zeitsperretyp_kurzbz,
|
||||
'vertretung_uid' => $vertretung_uid,
|
||||
'insertvon' => $loggedInUser,
|
||||
'insertamum' => date('c'),
|
||||
]
|
||||
);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
|
||||
public function update($zeitsperre_id)
|
||||
{
|
||||
//check if loggedin User is owner of the zeitsperre
|
||||
$loggedInUser = getAuthUID();
|
||||
$result = $this->ZeitsperreModel->load($zeitsperre_id);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
$uid = current($data)->mitarbeiter_uid;
|
||||
|
||||
if($uid != $loggedInUser)
|
||||
$this->terminateWithError($this->p->t('ui', 'noPermission'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
if(!$zeitsperre_id)
|
||||
{
|
||||
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Zeitsperre_id']), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
//get current params
|
||||
$array_update = [
|
||||
'bezeichnung',
|
||||
'vondatum',
|
||||
'vonstunde',
|
||||
'bisdatum',
|
||||
'bisstunde',
|
||||
// 'vonISO', //Timestamp für Stunde
|
||||
// 'bisISO', //Timestamp für Stunde
|
||||
'erreichbarkeit_kurzbz',
|
||||
'vertretung_uid',
|
||||
'zeitsperretyp_kurzbz',
|
||||
'mitarbeiter_uid',
|
||||
];
|
||||
$post = $this->input->post();
|
||||
$update = [];
|
||||
|
||||
foreach ($array_update as $prop)
|
||||
{
|
||||
if (array_key_exists($prop, $post))
|
||||
{
|
||||
$update[$prop] = $post[$prop];
|
||||
}
|
||||
}
|
||||
|
||||
// Validation
|
||||
$rulesDefined = false; //necessary, otherwise CI validation will always be triggered, even without rules
|
||||
foreach ($update as $key => $val) {
|
||||
switch ($key) {
|
||||
case 'zeitsperretyp_kurzbz':
|
||||
$this->form_validation->set_rules(
|
||||
$key,
|
||||
'Grund Zeitsperre',
|
||||
'required',
|
||||
['required' => $this->p->t('ui', 'error_fieldRequired', ['field'=>'Grund Zeitsperre'])]
|
||||
);
|
||||
$rulesDefined = true;
|
||||
break;
|
||||
case 'vondatum':
|
||||
$this->form_validation->set_rules(
|
||||
$key,
|
||||
'VonDatum',
|
||||
'required|is_valid_date',
|
||||
[
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field'=>'VonDatum']),
|
||||
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field'=>'VonDatum'])
|
||||
]
|
||||
);
|
||||
$rulesDefined = true;
|
||||
break;
|
||||
case 'bisdatum':
|
||||
$rules = 'required|is_valid_date';
|
||||
if (array_key_exists('vondatum', $update)) {
|
||||
$rules .= '|callback_check_von_bis_datum|callback_check_diff_intval';
|
||||
}
|
||||
$this->form_validation->set_rules(
|
||||
$key,
|
||||
'BisDatum',
|
||||
$rules,
|
||||
[
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field'=>'BisDatum']),
|
||||
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field'=>'BisDatum']),
|
||||
'check_von_bis_datum' => $this->p->t('zeitsperre', 'error_VonDatumGroesserAlsBisDatum'),
|
||||
'check_diff_intval' => $this->p->t('zeitsperre', 'error_zeitraumAuffallendHoch')
|
||||
]
|
||||
);
|
||||
$rulesDefined = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($rulesDefined && $this->form_validation->run() == false) {
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
}
|
||||
|
||||
if(array_key_exists('vondatum', $post) || array_key_exists('bisdatum', $post))
|
||||
{
|
||||
$result = $this->ZeitsperreModel->load($zeitsperre_id);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
$data = current($data);
|
||||
|
||||
$mitarbeiter_uid = array_key_exists('mitarbeiter_uid', $post) ? $update['mitarbeiter_uid'] : $data->mitarbeiter_uid;
|
||||
$vondatum = array_key_exists('vondatum', $post) ? $update['vondatum'] : $data->vondatum;
|
||||
$bisdatum = array_key_exists('bisdatum', $post) ? $update['bisdatum'] : $data->bisdatum;
|
||||
$vonstunde = array_key_exists('vonstunde', $post) ? $update['vonstunde'] : $data->vonstunde;
|
||||
$zeitsperretyp_kurzbz = array_key_exists('zeitsperretyp_kurzbz', $post) ? $update['zeitsperretyp_kurzbz'] : $data->zeitsperretyp_kurzbz;
|
||||
|
||||
$result = $this->ZeitsperreModel->getSperreByDate($mitarbeiter_uid, $vondatum, $vonstunde, true);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
if(hasData($result))
|
||||
{
|
||||
$this->terminateWithError($this->p->t('zeitsperren', 'error_existingZeitsperre', ['typ'=> current($data)->zeitsperretyp_kurzbz]), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
//check if existing zeitaufzeichnung
|
||||
if(in_array($zeitsperretyp_kurzbz, Zeitsperre_model::BLOCKIERENDE_ZEITSPERREN))
|
||||
{
|
||||
$result = $this->ZeitsperreModel->existsZeitaufzeichnung($mitarbeiter_uid, $vondatum, $bisdatum);
|
||||
|
||||
if(hasData($result))
|
||||
$this->terminateWithError($this->p->t('zeitsperren', 'error_existingZeitaufzeichnung'), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($update)) {
|
||||
$update['updatevon'] = $loggedInUser;
|
||||
$update['updateamum'] = date('c');
|
||||
$result = $this->ZeitsperreModel->update($zeitsperre_id, $update);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
else
|
||||
$this->terminateWithSuccess("no update");
|
||||
}
|
||||
|
||||
public function delete($zeitsperre_id)
|
||||
{
|
||||
|
||||
if (!is_numeric($zeitsperre_id) || (int)$zeitsperre_id <= 0)
|
||||
{
|
||||
$this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Zeitsperre_id']), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
//check if loggedin User is owner of the zeitsperre
|
||||
$loggedInUser = getAuthUID();
|
||||
$result = $this->ZeitsperreModel->load($zeitsperre_id);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
$uid = current($data)->mitarbeiter_uid;
|
||||
|
||||
if($uid != $loggedInUser)
|
||||
$this->terminateWithError($this->p->t('ui', 'noPermission'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
$result = $this->ZeitsperreModel->delete(
|
||||
array('zeitsperre_id' => $zeitsperre_id)
|
||||
);
|
||||
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
public function check_von_bis_datum($bisdatum)
|
||||
{
|
||||
$vondatum = $this->input->post('vondatum');
|
||||
|
||||
return $vondatum <= $bisdatum;
|
||||
}
|
||||
|
||||
public function check_diff_intval($bisdatum)
|
||||
{
|
||||
$vondatum = $this->input->post('vondatum');
|
||||
|
||||
// Intervall in days
|
||||
$vonTs = strtotime($vondatum);
|
||||
$bisTs = strtotime($bisdatum);
|
||||
|
||||
$tage = ($bisTs - $vonTs) / 86400;
|
||||
|
||||
// if intervall > 14
|
||||
return $tage <= 14;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -596,8 +596,8 @@ class Dokumente extends FHCAPI_Controller
|
||||
buildDropdownEntryPrintArray("bescheid", "Bescheid (nur Voransicht)", "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf", $uid, 25, null),
|
||||
buildDropdownEntryPrintArray("diplomasupp", "Diploma Supplement (nur Voransicht)", "xml=diplomasupplement.xml.php&xsl_stg_kz=$studiengang_kz&xsl=DiplSupplement&output=pdf", $uid, 26, null),
|
||||
|
||||
buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf", $uid, 50, null),
|
||||
buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf", $uid, 51, null),
|
||||
buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf&ss=$studiensemester_kurzbz&xsl_stg_kz=$studiengang_kz", $uid, 50, null),
|
||||
buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf&ss=$studiensemester_kurzbz&xsl_stg_kz=$studiengang_kz", $uid, 51, null),
|
||||
buildDropdownEntryPrintArray("zutrittskarte", "Zutrittskarte", "xsl=ZutrittskarteStud&output=pdf&data=$uid", $uid,200, "zutrittskarte.php"),
|
||||
buildDropdownEntryPrintArray("studienblatt", "Studienblatt", "xml=studienblatt.xml.php&xsl=Studienblatt&output=pdf&ss=$studiensemester_kurzbz", $uid, 60, null),
|
||||
buildDropdownEntryPrintArray("studienblatt_eng", "Studienblatt Englisch", "xml=studienblatt.xml.php&xsl=StudienblattEng&output=pdf&ss=$studiensemester_kurzbz", $uid, 61, null),
|
||||
@@ -686,8 +686,8 @@ class Dokumente extends FHCAPI_Controller
|
||||
buildDropdownEntryPrintArray("accountinfo", "Accountinfoblatt", "xml=accountinfoblatt.xml.php&xsl=AccountInfo&output=pdf", $uidString, 10, null),
|
||||
buildDropdownEntryPrintArray("ausbildungsvertrag", "Ausbildungsvertrag", "xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf", $uidString, 20, null),
|
||||
buildDropdownEntryPrintArray("ausbildungsvertrag_en", "Ausbildungsvertrag Englisch", "xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf", $uidString, 21, null),
|
||||
buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf", $uidString, 50, null),
|
||||
buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf", $uidString, 51, null),
|
||||
buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf&ss=$studiensemester_kurzbz&xsl_stg_kz=$studiengang_kz", $uidString, 50, null),
|
||||
buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf&ss=$studiensemester_kurzbz&xsl_stg_kz=$studiengang_kz", $uidString, 51, null),
|
||||
buildDropdownEntryPrintArray("zutrittskarte", "Zutrittskarte", "xsl=ZutrittskarteStud&output=pdf&data=$uidString", $uidString,200, "zutrittskarte.php"),
|
||||
buildDropdownEntryPrintArray("studienblatt", "Studienblatt", "xml=studienblatt.xml.php&xsl=Studienblatt&output=pdf&ss=$studiensemester_kurzbz", $uidString, 60, null),
|
||||
buildDropdownEntryPrintArray("studienblatt_eng", "Studienblatt Englisch", "xml=studienblatt.xml.php&xsl=StudienblattEng&output=pdf&ss=$studiensemester_kurzbz", $uidString, 61, null),
|
||||
|
||||
@@ -321,6 +321,10 @@ class Student extends FHCAPI_Controller
|
||||
foreach ($array_allowed_props_benutzer as $prop) {
|
||||
$val = $this->input->post($prop);
|
||||
if ($val !== null) {
|
||||
if($prop === 'alias' && $val === '')
|
||||
{
|
||||
$val = null;
|
||||
}
|
||||
$update_benutzer[$prop] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,8 +316,8 @@ class Lehrveranstaltung_model extends DB_Model
|
||||
(SELECT status_kurzbz FROM public.tbl_prestudentstatus WHERE prestudent_id=tbl_student.prestudent_id ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1) as status,
|
||||
tbl_bisio.bisio_id, tbl_bisio.von, tbl_bisio.bis, tbl_student.studiengang_kz AS stg_kz_student,
|
||||
tbl_zeugnisnote.note, tbl_mitarbeiter.mitarbeiter_uid, tbl_person.matr_nr, tbl_benutzer.uid,
|
||||
UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel, tbl_studiengang.orgform_kurzbz, vw_student_lehrveranstaltung.semester, vw_student_lehrveranstaltung.studiensemester_kurzbz, vw_student_lehrveranstaltung.bezeichnung
|
||||
|
||||
UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel, tbl_studiengang.orgform_kurzbz, vw_student_lehrveranstaltung.semester, vw_student_lehrveranstaltung.studiensemester_kurzbz, vw_student_lehrveranstaltung.bezeichnung,
|
||||
tbl_student.prestudent_id
|
||||
FROM
|
||||
campus.vw_student_lehrveranstaltung
|
||||
JOIN public.tbl_benutzer USING(uid)
|
||||
@@ -386,6 +386,37 @@ class Lehrveranstaltung_model extends DB_Model
|
||||
|
||||
return $this->execQuery($query, array($lehrveranstaltung_id, $studiensemester_kurzbz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get LV-Leitung of given Lehrveranstaltung ID and Studiensemester.
|
||||
*
|
||||
* @param $lehrveranstaltung_id
|
||||
* @param $studiensemester
|
||||
* @return array|stdClass|null
|
||||
*/
|
||||
public function getLvLeitung($lehrveranstaltung_id, $studiensemester)
|
||||
{
|
||||
$params = [$lehrveranstaltung_id, $studiensemester];
|
||||
|
||||
$qry = "
|
||||
SELECT
|
||||
vorname, nachname, mitarbeiter_uid, lehrfunktion_kurzbz
|
||||
FROM
|
||||
lehre.tbl_lehreinheit
|
||||
JOIN lehre.tbl_lehreinheitmitarbeiter lema USING (lehreinheit_id)
|
||||
JOIN public.tbl_benutzer b ON b.uid = lema.mitarbeiter_uid
|
||||
JOIN public.tbl_person p using (person_id)
|
||||
WHERE
|
||||
tbl_lehreinheit.lehrveranstaltung_id= ?
|
||||
AND tbl_lehreinheit.studiensemester_kurzbz = ?
|
||||
AND lehrfunktion_kurzbz = 'LV-Leitung'
|
||||
ORDER BY
|
||||
lema.insertamum DESC
|
||||
LIMIT 1
|
||||
";
|
||||
|
||||
return $this->execQuery($qry, $params);
|
||||
}
|
||||
/**
|
||||
* Gets all Leiter of Lehrveranstaltungsorganisationseinheit
|
||||
* @param $lehrveranstaltung_id
|
||||
|
||||
@@ -64,16 +64,16 @@ class Projektarbeit_model extends DB_Model
|
||||
if (isset($projekttyp))
|
||||
{
|
||||
if (is_array($projekttyp))
|
||||
$qry .= ' AND tbl_projektarbeit.projekttyp_kurzbz IN ?';
|
||||
$qry .= ' AND pa.projekttyp_kurzbz IN ?';
|
||||
else
|
||||
$qry .= ' AND tbl_projektarbeit.projekttyp_kurzbz=?';
|
||||
$qry .= ' AND pa.projekttyp_kurzbz=?';
|
||||
|
||||
$params[] = $projekttyp;
|
||||
}
|
||||
|
||||
if (isset($final))
|
||||
{
|
||||
$qry .= ' AND tbl_projektarbeit.final=?';
|
||||
$qry .= ' AND pa.final=?';
|
||||
$params[] = $final;
|
||||
}
|
||||
|
||||
|
||||
@@ -801,4 +801,73 @@ class Studiengang_model extends DB_Model
|
||||
|
||||
return $this->execReadOnlyQuery($qry, array($studiengang_kz, $orgform_kurzbz, $studiensemester_kurzbz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get active Studiengänge with Kuerzel by given Studiengang-Kennzahlen.
|
||||
* Helpful to easily get Studiengänge the user is entitled for.
|
||||
*
|
||||
* @param $studiengang_kz_arr
|
||||
* @param $studiensemester_kurzbz
|
||||
* @return array|stdClass|null Returns one row per Studiengang. Not considering the Orgforms.
|
||||
*/
|
||||
public function getByStgs($studiengang_kz_arr, $studiensemester_kurzbz)
|
||||
{
|
||||
if (is_numeric($studiengang_kz_arr))
|
||||
{
|
||||
$studiengang_kz_arr = [$studiengang_kz_arr];
|
||||
}
|
||||
|
||||
$qry = '
|
||||
SELECT
|
||||
DISTINCT stg.*, UPPER(typ::varchar(1) || kurzbz) AS kuerzel
|
||||
FROM
|
||||
public.tbl_studiengang stg
|
||||
JOIN lehre.tbl_studienordnung sto USING(studiengang_kz)
|
||||
JOIN lehre.tbl_studienplan stpl USING(studienordnung_id)
|
||||
JOIN lehre.tbl_studienplan_semester stplsem USING(studienplan_id)
|
||||
WHERE
|
||||
stg.studiengang_kz IN ?
|
||||
AND stplsem.studiensemester_kurzbz = ?
|
||||
ORDER BY
|
||||
stg.kurzbzlang
|
||||
';
|
||||
|
||||
return $this->execQuery($qry, [$studiengang_kz_arr, $studiensemester_kurzbz]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get OrgForms of given Studiengang and Studiensemester.
|
||||
*
|
||||
* @param $studiengang_kz
|
||||
* @param $studiensemester_kurzbz
|
||||
* @return array|stdClass|null
|
||||
*/
|
||||
public function getOrgformsByStg($studiengang_kz, $studiensemester_kurzbz)
|
||||
{
|
||||
$qry = '
|
||||
SELECT
|
||||
stpl.orgform_kurzbz
|
||||
FROM
|
||||
public.tbl_studiengang stg
|
||||
JOIN lehre.tbl_studienordnung sto USING(studiengang_kz)
|
||||
JOIN lehre.tbl_studienplan stpl USING(studienordnung_id)
|
||||
JOIN lehre.tbl_studienplan_semester stplsem USING(studienplan_id)
|
||||
WHERE
|
||||
stg.studiengang_kz = ?
|
||||
AND stg.aktiv = TRUE
|
||||
AND stplsem.studiensemester_kurzbz = ?
|
||||
GROUP BY
|
||||
stpl.orgform_kurzbz
|
||||
ORDER BY
|
||||
CASE stpl.orgform_kurzbz
|
||||
WHEN \'VZ\' THEN 1
|
||||
WHEN \'BB\' THEN 2
|
||||
WHEN \'DUA\' THEN 3
|
||||
ELSE 4
|
||||
END,
|
||||
stpl.orgform_kurzbz;
|
||||
';
|
||||
|
||||
return $this->execQuery($qry, [$studiengang_kz, $studiensemester_kurzbz]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,4 +535,53 @@ class Stundenplan_model extends DB_Model
|
||||
|
||||
return $this->execQuery($query, [$uid, $uid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Stundenplantermine for given Lehreinheit.
|
||||
*
|
||||
* @param $lehreinheit_id
|
||||
* @return array|stdClass|null
|
||||
*/
|
||||
public function getTermineByLe($lehreinheit_id)
|
||||
{
|
||||
$qry = '
|
||||
SELECT DISTINCT
|
||||
datum
|
||||
FROM
|
||||
lehre.vw_stundenplan
|
||||
WHERE
|
||||
lehreinheit_id = ?
|
||||
ORDER BY
|
||||
datum ASC
|
||||
';
|
||||
|
||||
return $this->execQuery($qry, [$lehreinheit_id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Stundenplantermine for given Lehrveranstaltung of given Studiensemester.
|
||||
*
|
||||
* @param $lehrveranstaltung_id
|
||||
* @param $studiensemester_kurzbz
|
||||
* @return array|stdClass|null
|
||||
*/
|
||||
public function getTermineByLv($lehrveranstaltung_id, $studiensemester_kurzbz)
|
||||
{
|
||||
$qry = '
|
||||
SELECT DISTINCT
|
||||
datum
|
||||
FROM
|
||||
lehre.vw_stundenplan
|
||||
WHERE
|
||||
lehreinheit_id IN (
|
||||
SELECT lehreinheit_id
|
||||
FROM lehre.tbl_lehreinheit
|
||||
WHERE lehrveranstaltung_id = ?
|
||||
AND studiensemester_kurzbz = ?
|
||||
)
|
||||
ORDER BY datum ASC
|
||||
';
|
||||
|
||||
return $this->execQuery($qry, [$lehrveranstaltung_id, $studiensemester_kurzbz]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,6 @@ class Zeitsperre_model extends DB_Model
|
||||
$this->pk = 'zeitsperre_id';
|
||||
}
|
||||
|
||||
const BLOCKIERENDE_ZEITSPERREN = ['Krank','Urlaub','ZA','DienstV','PflegeU','DienstF','CovidSB','CovidKS'];
|
||||
|
||||
/**
|
||||
* Save or update Zeitsperre.
|
||||
*
|
||||
@@ -63,128 +61,4 @@ class Zeitsperre_model extends DB_Model
|
||||
|
||||
return $this->execQuery($qry);
|
||||
}
|
||||
|
||||
/**
|
||||
* get Zeitsperren of a user
|
||||
*
|
||||
* @param $uid mitarbeiteruid
|
||||
* @param $bisgrenze @true show only entries of actual business year (1.9.- 31.8.)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getZeitsperrenUser($uid, $bisgrenze = true)
|
||||
{
|
||||
$qry = "
|
||||
SELECT
|
||||
tbl_zeitsperre.*, tbl_zeitsperretyp.*, tbl_erreichbarkeit.farbe AS erreichbarkeit_farbe,
|
||||
tbl_erreichbarkeit.beschreibung AS erreichbarkeit_beschreibung,
|
||||
CONCAT (ps.vorname, ' ', ps.nachname) as vertretung
|
||||
FROM (campus.tbl_zeitsperre JOIN campus.tbl_zeitsperretyp USING (zeitsperretyp_kurzbz))
|
||||
LEFT JOIN campus.tbl_erreichbarkeit USING (erreichbarkeit_kurzbz)
|
||||
LEFT JOIN public.tbl_benutzer ON campus.tbl_zeitsperre.vertretung_uid = public.tbl_benutzer.uid
|
||||
LEFT JOIN public.tbl_person ps USING (person_id)
|
||||
WHERE mitarbeiter_uid= ?
|
||||
";
|
||||
|
||||
if($bisgrenze)
|
||||
{
|
||||
$qry.="
|
||||
AND (
|
||||
(date_part('month',vondatum)>=9 AND date_part('year', vondatum)>='".(date('Y')-1)."')
|
||||
OR
|
||||
(date_part('month',vondatum)<9 AND date_part('year', vondatum)>='".(date('Y'))."')
|
||||
)";
|
||||
}
|
||||
|
||||
$qry.= " ORDER BY vondatum DESC";
|
||||
|
||||
return $this->execQuery($qry, array('mitarbeiter_uid' => $uid));
|
||||
}
|
||||
|
||||
/**
|
||||
* check a date for existing zeitsperre
|
||||
*
|
||||
* @param $uid mitarbeiteruid
|
||||
* @param $datum datum to check
|
||||
* @param $stunde stunde (default = null)
|
||||
* @param bool $nurblockierend if only hr relevante zeitsperren have to be checked
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSperreByDate($uid, $datum, $stunde = null, $nurblockierend = false)
|
||||
{
|
||||
$parametersArray = [$datum, $datum];
|
||||
|
||||
$qry = "
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
campus.tbl_zeitsperre
|
||||
WHERE
|
||||
vondatum <= ?
|
||||
AND bisdatum>= ?";
|
||||
|
||||
if($nurblockierend)
|
||||
{
|
||||
$qry .= " AND zeitsperretyp_kurzbz IN ('"
|
||||
. implode("','", self::BLOCKIERENDE_ZEITSPERREN)
|
||||
. "')";
|
||||
}
|
||||
|
||||
if(!is_null($stunde))
|
||||
{
|
||||
$parametersArray = array_merge(
|
||||
$parametersArray,
|
||||
[$datum, $stunde, $datum, $datum, $stunde, $datum]
|
||||
);
|
||||
|
||||
$qry.=" AND
|
||||
((vondatum= ? AND vonstunde<= ? OR vonstunde is null OR vondatum<> ?) AND
|
||||
(bisdatum= ? AND bisstunde>= ? OR bisstunde is null OR bisdatum<> ?))";
|
||||
}
|
||||
|
||||
array_push($parametersArray, $uid);
|
||||
|
||||
$qry .= "AND mitarbeiter_uid= ? ";
|
||||
|
||||
return $this->execQuery($qry, $parametersArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* check a date for existing zeitsperre
|
||||
*
|
||||
* @param $uid mitarbeiteruid
|
||||
* @param $vondatum datum in Format IS0
|
||||
* @param $bisdatum datum in Format ISO
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function existsZeitaufzeichnung($uid, $vonDay, $bisDay)
|
||||
{
|
||||
try {
|
||||
$from = new DateTime($vonDay);
|
||||
$to = new DateTime($bisDay);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("Invalid date format");
|
||||
}
|
||||
|
||||
//remove hour stamps
|
||||
$from->setTime(0, 0, 0);
|
||||
$to->setTime(0, 0, 0)->modify('+1 day');
|
||||
|
||||
$fromSql = $from->format('Y-m-d');
|
||||
$toSql = $to->format('Y-m-d');
|
||||
$params = [$uid, $fromSql, $toSql];
|
||||
|
||||
$qry = "
|
||||
SELECT *
|
||||
FROM campus.tbl_zeitaufzeichnung
|
||||
WHERE uid = ?
|
||||
AND start >= ?
|
||||
AND ende < ? ";
|
||||
|
||||
$result = $this->execQuery($qry, $params);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ $includesArray = array(
|
||||
'public/css/components/FormUnderline.css',
|
||||
'public/css/Cis4/Cms.css',
|
||||
'public/css/Cis4/Studium.css',
|
||||
'public/css/Cis4/Zeitsperren.css',
|
||||
),
|
||||
'customJSs' => array(
|
||||
'vendor/npm-asset/primevue/accordion/accordion.min.js',
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
(function () {
|
||||
function sendMessage() {
|
||||
let frame = window.frames['content'];
|
||||
if (frame)
|
||||
frame.postMessage({ type: "proctoringReady" });
|
||||
}
|
||||
|
||||
window.addEventListener("message", function (e)
|
||||
{
|
||||
if (e.data.indexOf("proctoringReady_") === 0)
|
||||
{
|
||||
sendMessage();
|
||||
}
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,30 @@
|
||||
.proctoring-blocker
|
||||
{
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 99999;
|
||||
backdrop-filter: blur(6px);
|
||||
pointer-events: all;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.proctoring-blocker.hidden
|
||||
{
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.proctoring-text
|
||||
{
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.proctoring-blur-fallback
|
||||
{
|
||||
filter: blur(6px);
|
||||
}
|
||||
@@ -45,7 +45,7 @@ if (!$db = new basis_db())
|
||||
$PHP_SELF=$_SERVER["PHP_SELF"];
|
||||
|
||||
// Start session
|
||||
session_start();
|
||||
require_once './session_init.php';
|
||||
|
||||
// If language is changed by language select menu, reset language variables
|
||||
if (isset($_GET['sprache_user']) && !empty($_GET['sprache_user']))
|
||||
@@ -182,6 +182,12 @@ echo '
|
||||
if(!isset($_SESSION['pruefling_id']))
|
||||
die($p->t('testtool/bitteZuerstAnmelden'));
|
||||
|
||||
if (!empty($_SESSION['externe_ueberwachung']) && isset($_SESSION['externe_ueberwachung_verified'])): ?>
|
||||
<link href="frage.css" rel="stylesheet" type="text/css" />
|
||||
<script type="text/javascript" src="frage_externe_ueberwachung.js"></script>
|
||||
<div id="proctoringBlocker" class="proctoring-blocker hidden"></div>
|
||||
<?php endif;
|
||||
|
||||
$pruefling = new pruefling();
|
||||
$pruefling->load($_SESSION['pruefling_id']);
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
(function () {
|
||||
let ok = false;
|
||||
let blocker;
|
||||
|
||||
function showBlocker() {
|
||||
blocker = document.getElementById("proctoringBlocker");
|
||||
|
||||
if (!blocker)
|
||||
{
|
||||
blocker = document.createElement("div");
|
||||
blocker.id = "proctoringBlocker";
|
||||
blocker.className = "proctoring-blocker";
|
||||
blocker.innerHTML = '<div class="proctoring-text">Loading...</div>';
|
||||
document.body.appendChild(blocker);
|
||||
}
|
||||
document.documentElement.classList.add("proctoring-blur-fallback");
|
||||
}
|
||||
|
||||
function block() {
|
||||
showBlocker();
|
||||
blocker.classList.remove("hidden");
|
||||
}
|
||||
|
||||
function unblock() {
|
||||
document.documentElement.classList.remove("proctoring-blur-fallback");
|
||||
if (!blocker) return;
|
||||
blocker.classList.add("hidden");
|
||||
}
|
||||
|
||||
const blockTimer = setTimeout(function () {
|
||||
if (!ok)
|
||||
block();
|
||||
}, 1500);
|
||||
|
||||
window.addEventListener("message", function (e) {
|
||||
const data = e.data || {};
|
||||
|
||||
if (data.type === "proctoringReady")
|
||||
{
|
||||
ok = true;
|
||||
clearTimeout(blockTimer);
|
||||
unblock();
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
if (!ok) {
|
||||
top.location.href = "resetconnection.php";
|
||||
}
|
||||
}, 3000);
|
||||
})();
|
||||
|
||||
|
||||
@@ -1,16 +1,79 @@
|
||||
<?php
|
||||
$contentpage = 'login.php';
|
||||
|
||||
require_once './session_init.php';
|
||||
|
||||
if(isset($_GET['prestudent']) && is_numeric($_GET['prestudent']))
|
||||
{
|
||||
$contentpage = 'login.php?prestudent='.$_GET['prestudent'];
|
||||
}
|
||||
|
||||
if ((isset($_SESSION['externe_ueberwachung']) && $_SESSION['externe_ueberwachung'] === true) &&
|
||||
isset($_SESSION['externe_ueberwachung_verified']) && $_SESSION['externe_ueberwachung_verified'] === false)
|
||||
{
|
||||
header("Location: resetconnection.php");
|
||||
exit;
|
||||
}
|
||||
?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>TestTool - FH Technikum Wien</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<link href="../../skin/style.css.php" rel="stylesheet" type="text/css">
|
||||
<?php
|
||||
if (!empty($_SESSION['externe_ueberwachung'])) : ?>
|
||||
<script type="text/javascript" src="externeueberwachung.js"></script>
|
||||
<script>
|
||||
function loadInContent(url)
|
||||
{
|
||||
if (url.includes('logout=true'))
|
||||
{
|
||||
return doLogout(url);
|
||||
}
|
||||
|
||||
let frame = document.getElementById('content_testtool');
|
||||
if (frame)
|
||||
{
|
||||
frame.src = url;
|
||||
}
|
||||
}
|
||||
|
||||
function doLogout(url)
|
||||
{
|
||||
fetch(url)
|
||||
let topbarFrame = window.frames['topbar'];
|
||||
let menuFrame = window.frames['menu'];
|
||||
let contentFrame = window.frames['content'];
|
||||
|
||||
if (contentFrame)
|
||||
contentFrame.location.href = 'logout.html';
|
||||
|
||||
if (menuFrame)
|
||||
menuFrame.location.href = menuFrame.location.pathname;
|
||||
|
||||
if (topbarFrame)
|
||||
topbarFrame.location.href = topbarFrame.location.pathname;
|
||||
return false;
|
||||
}
|
||||
|
||||
function changeSprache(content_params, sprache)
|
||||
{
|
||||
let topbarFrame = window.frames['topbar'];
|
||||
let menuFrame = window.frames['menu'];
|
||||
let contentFrame = window.frames['content'];
|
||||
|
||||
if (topbarFrame)
|
||||
topbarFrame.location.href = topbarFrame.location.pathname + '?sprache_user=' + sprache;
|
||||
|
||||
if (menuFrame)
|
||||
menuFrame.location.href = menuFrame.location.pathname + '?sprache_user=' + sprache;
|
||||
|
||||
if (contentFrame)
|
||||
contentFrame.location.href = contentFrame.location.pathname + '?' + content_params;
|
||||
}
|
||||
|
||||
</script>
|
||||
<?php endif; ?>
|
||||
</head>
|
||||
|
||||
<frameset rows="13%,*" cols="*" frameborder="NO" border="0" framespacing="0">
|
||||
@@ -26,3 +89,4 @@ if(isset($_GET['prestudent']) && is_numeric($_GET['prestudent']))
|
||||
</noframes>
|
||||
</frameset>
|
||||
</html>
|
||||
|
||||
|
||||
+23
-4
@@ -40,8 +40,7 @@ if (!$db = new basis_db())
|
||||
die('Fehler beim Oeffnen der Datenbankverbindung');
|
||||
|
||||
// Start session
|
||||
session_start();
|
||||
|
||||
require_once './session_init.php';
|
||||
// Logout (triggered by logout button in menu.php)
|
||||
if (isset($_GET['logout']) && $_GET['logout'] == true)
|
||||
{
|
||||
@@ -173,6 +172,12 @@ if (isset($_REQUEST['prestudent']))
|
||||
else
|
||||
$reload_menu = true;
|
||||
}
|
||||
|
||||
if ($rt->externe_ueberwachung && defined('TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED') && TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED)
|
||||
{
|
||||
$_SESSION['externe_ueberwachung'] = true;
|
||||
$_SESSION['externe_ueberwachung_verified'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
$pruefling = new pruefling();
|
||||
@@ -339,6 +344,8 @@ if ((isset($_SESSION['prestudent_id']) && !isset($_SESSION['pruefling_id']) &&
|
||||
!isset($_SESSION['confirmation_needed']) && !isset($_SESSION['confirmed_code'])) ||
|
||||
(isset($_SESSION['confirmation_needed']) && $_SESSION['confirmation_needed'] === true &&
|
||||
isset($_SESSION['confirmed_code']) && $_SESSION['confirmed_code'] === true &&
|
||||
isset($_SESSION['externe_ueberwachung']) && $_SESSION['externe_ueberwachung'] === true &&
|
||||
isset($_SESSION['externe_ueberwachung_verified']) && $_SESSION['externe_ueberwachung_verified'] === true &&
|
||||
isset($_SESSION['prestudent_id']) && !isset($_SESSION['pruefling_id'])))
|
||||
{
|
||||
$pruefling = new pruefling();
|
||||
@@ -460,7 +467,13 @@ if (isset($_POST['save']) && isset($_SESSION['prestudent_id']))
|
||||
|
||||
<?php
|
||||
|
||||
if (isset($_SESSION['confirmation_needed']) && $_SESSION['confirmation_needed'] === true &&
|
||||
if ((isset($_SESSION['externe_ueberwachung']) && $_SESSION['externe_ueberwachung'] === true) &&
|
||||
isset($_SESSION['externe_ueberwachung_verified']) && $_SESSION['externe_ueberwachung_verified'] === false)
|
||||
{
|
||||
echo "<script> top.location.href = 'resetconnection.php';</script>";
|
||||
exit;
|
||||
}
|
||||
else if (isset($_SESSION['confirmation_needed']) && $_SESSION['confirmation_needed'] === true &&
|
||||
isset($_SESSION['confirmed_code']) && $_SESSION['confirmed_code'] === false)
|
||||
{
|
||||
echo '
|
||||
@@ -718,7 +731,7 @@ else // LOGIN Site (vor Login)
|
||||
echo '<script>
|
||||
function changeconfirmation()
|
||||
{
|
||||
document.getElementById("confirmationSubmit").disabled = !document.getElementById("confirmationCheckbox").checked;
|
||||
document.getElementById("confirmationSubmit").disabled = !document.getElementById("confirmationCheckbox").checked || !document.getElementById("dsgvoconfirm").checked || !document.getElementById("procotoringconfirm").checked;
|
||||
}
|
||||
</script>';
|
||||
echo '<div class="row text-center">
|
||||
@@ -728,6 +741,12 @@ else // LOGIN Site (vor Login)
|
||||
<input id="confirmationCheckbox" type="checkbox" name="confirmation" onclick="changeconfirmation()" />
|
||||
'.$p->t('testtool/confirmationText').'
|
||||
<br><br>
|
||||
<input id="dsgvoconfirm" type="checkbox" name="confirmation" onclick="changeconfirmation()" />
|
||||
'.$p->t('testtool/dsgvoConfirmText').'
|
||||
<br><br>
|
||||
<input id="procotoringconfirm" type="checkbox" name="confirmation" onclick="changeconfirmation()" />
|
||||
'.$p->t('testtool/procotoringConfirmText').'
|
||||
<br><br>
|
||||
<button id="confirmationSubmit" type="submit" class="btn btn-primary" disabled/>
|
||||
'.$p->t('testtool/start').'
|
||||
</button>
|
||||
|
||||
+31
-7
@@ -34,7 +34,7 @@ if (!$db = new basis_db())
|
||||
die('Fehler beim Oeffnen der Datenbankverbindung');
|
||||
|
||||
// Start session
|
||||
session_start();
|
||||
require_once './session_init.php';
|
||||
|
||||
// If language is changed by language select menu, reset language and session variables
|
||||
if(isset($_GET['sprache_user']) && !empty($_GET['sprache_user']))
|
||||
@@ -61,8 +61,12 @@ $p = new phrasen($sprache_user);
|
||||
<?php
|
||||
$gebiet_hasMathML = false; // true, wenn irgendein Gebiet eine/n Frage/Vorschlag im MathML-Format enthält
|
||||
$invalid_gebiete = false;
|
||||
|
||||
if (isset($_SESSION['pruefling_id']))
|
||||
if ((isset($_SESSION['externe_ueberwachung']) && $_SESSION['externe_ueberwachung'] === true) &&
|
||||
isset($_SESSION['externe_ueberwachung_verified']) && $_SESSION['externe_ueberwachung_verified'] === false)
|
||||
{
|
||||
exit;
|
||||
}
|
||||
else if (isset($_SESSION['pruefling_id']))
|
||||
{
|
||||
//content_id fuer Einfuehrung auslesen
|
||||
$qry = "SELECT content_id FROM testtool.tbl_ablauf_vorgaben WHERE studiengang_kz=".$db->db_add_param($_SESSION['studiengang_kz'])." LIMIT 1";
|
||||
@@ -73,7 +77,7 @@ if (isset($_SESSION['pruefling_id']))
|
||||
|
||||
// Link zur Startseite
|
||||
echo '<tr><td class="ItemTesttool" style="margin-left: 20px;" nowrap>
|
||||
<a class="ItemTesttool navButton" href="login.php" target="content">'.$p->t('testtool/startseite').'</a>
|
||||
<a class="ItemTesttool navButton" href="login.php" onclick="return loadContent(this.href);">'.$p->t('testtool/startseite').'</a>
|
||||
</td></tr>';
|
||||
|
||||
// Link zur Einleitung
|
||||
@@ -83,7 +87,7 @@ if (isset($_SESSION['pruefling_id']))
|
||||
{
|
||||
echo '
|
||||
<tr id="tr-einleitung"><td class="ItemTesttool" style="margin-left: 20px;" nowrap>
|
||||
<a class="ItemTesttool navButton" href="../../cms/content.php?content_id='.$content_id->content_id.'&sprache='.$sprache_user.'" target="content">'.$p->t('testtool/einleitung').'</a>
|
||||
<a class="ItemTesttool navButton" href="../../cms/content.php?content_id='.$content_id->content_id.'&sprache='.$sprache_user.'" onclick="return loadContent(this.href);">'.$p->t('testtool/einleitung').'</a>
|
||||
</td></tr>
|
||||
';
|
||||
}
|
||||
@@ -379,10 +383,13 @@ if (isset($_SESSION['pruefling_id']))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
echo '<tr>
|
||||
<!--<td width="10" class="ItemTesttoolLeft" nowrap> </td>-->
|
||||
|
||||
<td class="'.$class.'">
|
||||
<a class="'.$class.'" href="frage.php?gebiet_id='.$row->gebiet_id.'" onclick="document.location.reload()" target="content" style="'.$style.'">'.$gebietbezeichnung.'</a>
|
||||
<a class="'.$class.'" href="frage.php?gebiet_id='.$row->gebiet_id.'" onclick="return loadContent(this.href);" style="'.$style.'">'.$gebietbezeichnung.'</a>
|
||||
|
||||
</td>
|
||||
<!--<td width="10" class="ItemTesttoolRight" nowrap> </td>-->
|
||||
</tr>';
|
||||
@@ -401,7 +408,7 @@ if (isset($_SESSION['pruefling_id']))
|
||||
// Link zum Logout
|
||||
|
||||
echo '<tr><td class="ItemTesttool" style="margin-left: 20px;" nowrap>
|
||||
<a class="ItemTesttool navButton" href="login.php?logout=true" target="content">Logout</a>
|
||||
<a class="ItemTesttool navButton" href="login.php?logout=true" onclick="return loadContent(this.href);">Logout</a>
|
||||
</td></tr>';
|
||||
|
||||
echo '</td></tr></table>';
|
||||
@@ -439,5 +446,22 @@ else
|
||||
'</td></tr>');
|
||||
}
|
||||
});
|
||||
|
||||
function loadContent(url)
|
||||
{
|
||||
if (parent && typeof parent.loadInContent === 'function')
|
||||
{
|
||||
parent.loadInContent(url);
|
||||
return false;
|
||||
}
|
||||
|
||||
let frame = parent?.frames?.["content"];
|
||||
if (frame)
|
||||
{
|
||||
frame.location.href = url;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
|
||||
require_once './session_init.php';
|
||||
|
||||
require_once('../../config/cis.config.inc.php');
|
||||
require_once('../../config/global.config.inc.php');
|
||||
require_once '../../include/externe_ueberwachung.class.php';
|
||||
if (!$db = new basis_db())
|
||||
die('Fehler beim Oeffnen der Datenbankverbindung');
|
||||
if ((defined('TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED') && TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED) && isset($_SESSION['externe_ueberwachung']) && $_SESSION['externe_ueberwachung'] === true)
|
||||
{
|
||||
$ueberwachung = new externeUeberwachung();
|
||||
$url = $ueberwachung->start($_SESSION['prestudent_id'], $_SESSION['reihungstestID'], $_SESSION['sprache']);
|
||||
$urlSafe = htmlspecialchars($url, ENT_QUOTES);
|
||||
header("Location: $urlSafe");
|
||||
$_SESSION['externe_ueberwachung_verified'] = true;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_set_cookie_params(
|
||||
0,
|
||||
'/; samesite=None',
|
||||
'',
|
||||
true,
|
||||
true
|
||||
);
|
||||
session_start();
|
||||
}
|
||||
+11
-3
@@ -67,9 +67,17 @@ function changeSprache(sprache)
|
||||
content_params.set('sprache_user', sprache); // add or replace sprache_user
|
||||
|
||||
// Pass GET-param sprache_user to topbar.php, menu.php and content (login.php or frage.php) and refresh the frames.
|
||||
location.href = location.pathname + '?sprache_user=' + sprache; // refreshes topbar.php
|
||||
parent.menu.location.href = parent.menu.location.pathname + '?sprache_user=' + sprache; // refreshes menu.php
|
||||
parent.content.location.href = parent.content.location.pathname + '?' + content_params; // refreshes login.php or frage.php
|
||||
if (parent && typeof parent.changeSprache === 'function')
|
||||
{
|
||||
parent.changeSprache(content_params, sprache);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
location.href = location.pathname + '?sprache_user=' + sprache; // refreshes topbar.php
|
||||
parent.menu.location.href = parent.menu.location.pathname + '?sprache_user=' + sprache; // refreshes menu.php
|
||||
parent.content.location.href = parent.content.location.pathname + '?' + content_params; // refreshes login.php or frage.php
|
||||
}
|
||||
}
|
||||
|
||||
$(document).on("keydown", function (e) {
|
||||
|
||||
@@ -456,6 +456,7 @@
|
||||
"fortawesome/font-awesome4": "4.7.*",
|
||||
"fortawesome/font-awesome6": "6.1.*",
|
||||
"fzaninotto/faker": "1.*",
|
||||
"firebase/php-jwt": "^6.0",
|
||||
|
||||
"highcharts/highcharts-dist": "^7.1.2",
|
||||
|
||||
|
||||
Generated
+58
-1
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "1de37a74ba51a66057eb2712b21340c8",
|
||||
"content-hash": "f4f0af4586f46f97d8b6092c1ac0fb3a",
|
||||
"packages": [
|
||||
{
|
||||
"name": "afarkas/html5shiv",
|
||||
@@ -882,6 +882,63 @@
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
{
|
||||
"name": "firebase/php-jwt",
|
||||
"version": "v6.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/firebase/php-jwt.git",
|
||||
"reference": "0541cba75ab108ef901985e68055a92646c73534"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/firebase/php-jwt/zipball/0541cba75ab108ef901985e68055a92646c73534",
|
||||
"reference": "0541cba75ab108ef901985e68055a92646c73534",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": ">=4.8 <=9"
|
||||
},
|
||||
"suggest": {
|
||||
"paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Firebase\\JWT\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Neuman Vong",
|
||||
"email": "[email protected]",
|
||||
"role": "Developer"
|
||||
},
|
||||
{
|
||||
"name": "Anant Narayanan",
|
||||
"email": "[email protected]",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
|
||||
"homepage": "https://github.com/firebase/php-jwt",
|
||||
"keywords": [
|
||||
"jwt",
|
||||
"php"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/firebase/php-jwt/issues",
|
||||
"source": "https://github.com/firebase/php-jwt/tree/v6.0.0"
|
||||
},
|
||||
"time": "2022-01-24T15:18:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "fortawesome/font-awesome4",
|
||||
"version": "4.7.0",
|
||||
|
||||
@@ -301,4 +301,16 @@ define ('DEFAULT_ECHTER_DIENSTVERTRAG',[103,111]);
|
||||
|
||||
// Weiterleiten zu CIS neu (wenn Rechte vorhanden)
|
||||
define('CIS_REDIRECT_TO_CIS4', false);
|
||||
|
||||
//Externe Ueberwachung
|
||||
define('EXTERNE_UEBERWACHUNG_PROTOCOL_URL', 'https://example.com');
|
||||
define('EXTERNE_UEBERWACHUNG_SECRET_KEY', null);
|
||||
define('EXTERNE_UEBERWACHUNG_INTEGRATION_NAME', 'example');
|
||||
define('EXTERNE_UEBERWACHUNG_SESSION_URL', 'https://example.com');
|
||||
define('EXTERNE_UEBERWACHUNG_TRIAL_TEST', false);
|
||||
define('EXTERNE_UEBERWACHUNG_EXAM_PARAMS', []);
|
||||
define('EXTERNE_UEBERWACHUNG_EXAM_RULES', []);
|
||||
define('EXTERNE_UEBERWACHUNG_EXAM_SCORE', []);
|
||||
|
||||
|
||||
?>
|
||||
|
||||
@@ -28,11 +28,15 @@ define('CIS_LEHRVERANSTALTUNG_LEHRFACH_ANZEIGEN',false);
|
||||
define('CIS_LEHRVERANSTALTUNG_GESAMTNOTE_ANZEIGEN', true);
|
||||
define('CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN', true);
|
||||
define('CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN', true);
|
||||
define('CIS_LEHRVERANSTALTUNG_EVALUIERUNG_ANZEIGEN', true);
|
||||
|
||||
// Wenn gesetzt, werden die Digitale Anwesenheit-Icons nur fuer diese Studiengaenge angezeigt, sonst für alle
|
||||
// define('CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN_STG', serialize(array('257')));
|
||||
// define('CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN_LVA', serialize(array('39455','39481','39480','41906','41905','41904','39459','39512','39454','39482','42230','42231','39458','41921','41922','39457','42896')));
|
||||
|
||||
// Wenn gesetzt, werden die LV-Evaluierung-Icons nur für diese Studiengaenge angezeigt, sonst alle
|
||||
define('CIS_EVALUIERUNG_ANZEIGEN_STG', serialize((array('335', '585', '914', '298')))); // BIW, MAI, BUB, MIO
|
||||
|
||||
// Im CIS Menue Links bei Modulen anzeigen wenn Lehrauftrag
|
||||
define('CIS_LEHRVERANSTALTUNG_MODULE_LINK',true);
|
||||
|
||||
@@ -364,4 +368,7 @@ define('SANCHO_MAIL_FOOTER_IMG', 'sancho_footer_DEFAULT.jpg');
|
||||
// Gibt an, ob in der StudVW der Status vorgerueckt werden kann
|
||||
define('STATUS_VORRUECKEN_ANZEIGEN', true);
|
||||
|
||||
//externe Ueberwachung im Testtool erlauben
|
||||
define('TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED', false);
|
||||
|
||||
?>
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
|
||||
require_once(dirname(__FILE__).'/basis_db.class.php');
|
||||
require_once(dirname(__FILE__).'/prestudent.class.php');
|
||||
require_once(dirname(__FILE__).'/person.class.php');
|
||||
require_once(dirname(__FILE__).'/reihungstest.class.php');
|
||||
|
||||
require_once(dirname(__FILE__).'/../vendor/autoload.php');
|
||||
use Firebase\JWT\JWT;
|
||||
|
||||
class externeUeberwachung extends basis_db
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function getStatusByPrestudent($prestudent_id)
|
||||
{
|
||||
$session_id = $this->getSessionByPrestudent($prestudent_id);
|
||||
return $this->getSessionStatus($session_id);
|
||||
}
|
||||
public function start($prestudent_id, $reihungstest_id, $sprache)
|
||||
{
|
||||
$session_id = $this->getSessionByPrestudent($prestudent_id);
|
||||
|
||||
if (!$session_id)
|
||||
{
|
||||
$session_id = $this->createSession($prestudent_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
$status = $this->getSessionStatus($session_id);
|
||||
|
||||
if (in_array($status, array('late_to_start', 'finished')))
|
||||
{
|
||||
$session_id = $this->createSession($prestudent_id);
|
||||
}
|
||||
}
|
||||
|
||||
$payload = $this->getPayload($session_id, $prestudent_id, $reihungstest_id, $sprache);
|
||||
return $this->getStartUrl($payload);
|
||||
}
|
||||
|
||||
|
||||
private function createSession($prestudent_id)
|
||||
{
|
||||
if (is_null($prestudent_id))
|
||||
{
|
||||
$this->errormsg = 'Falsche Parameterübergabe';
|
||||
return false;
|
||||
}
|
||||
|
||||
$uuid = $this->genereateUUID();
|
||||
|
||||
$qry = "INSERT INTO testtool.tbl_externe_ueberwachung (prestudent_id, session_id)
|
||||
VALUES (".
|
||||
$this->db_add_param($prestudent_id).",".
|
||||
$this->db_add_param($uuid).")";
|
||||
|
||||
if($this->db_query($qry))
|
||||
{
|
||||
return $uuid;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->errormsg = 'Fehler beim Speichern der Antwort';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
public function getSessionByPrestudent($prestudent_id)
|
||||
{
|
||||
if (is_null($prestudent_id))
|
||||
{
|
||||
$this->errormsg = 'Falsche Parameterübergabe';
|
||||
return false;
|
||||
}
|
||||
|
||||
$qry = "SELECT session_id
|
||||
FROM testtool.tbl_externe_ueberwachung
|
||||
WHERE prestudent_id = ".$this->db_add_param($prestudent_id, FHC_INTEGER) . "
|
||||
ORDER BY insertamum DESC
|
||||
LIMIT 1";
|
||||
|
||||
if($result = $this->db_query($qry))
|
||||
{
|
||||
if ($row = $this->db_fetch_object($result))
|
||||
{
|
||||
return $row->session_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->errormsg = 'Daten konnten nicht geladen werden';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->errormsg = 'Fehler bei einer Abfrage';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getSessionStatus($session_id)
|
||||
{
|
||||
$payload = $this->getSessionPayload($session_id);
|
||||
$jwt = $this->createToken($payload);
|
||||
|
||||
$url = $this->getSessionUrl($session_id);
|
||||
|
||||
$ch = curl_init($url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
"Authorization: JWT {$jwt}",
|
||||
"Content-Type: application/json",
|
||||
]);
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
$data = json_decode($response, true);
|
||||
return isset($data['status']) ? $data['status'] : false;
|
||||
}
|
||||
|
||||
private function getSessionPayload($session_id)
|
||||
{
|
||||
return [
|
||||
"session_id" => $session_id,
|
||||
"iat" => time(),
|
||||
"exp" => time() + 120,
|
||||
];
|
||||
}
|
||||
|
||||
private function getPayload($session_id, $prestudent_id, $reihungstest_id, $sprache)
|
||||
{
|
||||
$prestudent = new prestudent($prestudent_id);
|
||||
$person = new Person($prestudent->person_id);
|
||||
|
||||
$reihungstest = new Reihungstest($reihungstest_id);
|
||||
|
||||
$datetime = new DateTime();
|
||||
$today = $datetime->format('Y-m-d');
|
||||
|
||||
$payload = [
|
||||
"userId" => $prestudent_id,
|
||||
"lastName" => $person->nachname,
|
||||
"firstName" => $person->vorname,
|
||||
"language" => $sprache === 'German' ? 'de' : 'en',
|
||||
"accountName" => "technikum_wien",
|
||||
"accountId" => "technikum_wien",
|
||||
"examId" => $reihungstest_id . '_' . $today,
|
||||
"examName" => !is_null(trim($reihungstest->anmerkung)) ? ($reihungstest->anmerkung . '_' . $today) : ($reihungstest_id . '_' . $today),
|
||||
"duration" => 1440,
|
||||
"schedule" => false,
|
||||
"trial" => EXTERNE_UEBERWACHUNG_TRIAL_TEST,
|
||||
"proctoring" => "offline",
|
||||
"startDate" => $reihungstest->datum . 'T00:00:00Z',
|
||||
"endDate" => $reihungstest->datum . 'T23:59:59Z',
|
||||
"sessionId" => $session_id,
|
||||
"sessionUrl" => EXTERNE_UEBERWACHUNG_SESSION_URL
|
||||
];
|
||||
|
||||
if (defined('EXTERNE_UEBERWACHUNG_EXAM_PARAMS'))
|
||||
{
|
||||
$payload = array_merge($payload, EXTERNE_UEBERWACHUNG_EXAM_PARAMS);
|
||||
}
|
||||
|
||||
if (defined('EXTERNE_UEBERWACHUNG_EXAM_RULES'))
|
||||
{
|
||||
$payload['rules'] = EXTERNE_UEBERWACHUNG_EXAM_RULES;
|
||||
}
|
||||
|
||||
if (defined('EXTERNE_UEBERWACHUNG_EXAM_SCORE'))
|
||||
{
|
||||
$payload['scoreConfig'] = EXTERNE_UEBERWACHUNG_EXAM_SCORE;
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
private function getSessionUrl($session_id)
|
||||
{
|
||||
return EXTERNE_UEBERWACHUNG_PROTOCOL_URL . "/api/v2/integration/simple/". EXTERNE_UEBERWACHUNG_INTEGRATION_NAME . "/sessions/". urlencode($session_id) ."/status/";
|
||||
}
|
||||
|
||||
private function getStartUrl($payload)
|
||||
{
|
||||
$token = $this->createToken($payload);
|
||||
$query = http_build_query(['token' => $token]);
|
||||
|
||||
return EXTERNE_UEBERWACHUNG_PROTOCOL_URL . '/integration/simple/'. EXTERNE_UEBERWACHUNG_INTEGRATION_NAME .'/start?' . $query;
|
||||
}
|
||||
|
||||
private function createToken($payload)
|
||||
{
|
||||
return JWT::encode($payload, EXTERNE_UEBERWACHUNG_SECRET_KEY, 'HS256');
|
||||
}
|
||||
|
||||
private function genereateUUID()
|
||||
{
|
||||
$data = openssl_random_pseudo_bytes(16);
|
||||
|
||||
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
|
||||
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
|
||||
|
||||
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ class lehrveranstaltung extends basis_db
|
||||
public $farbe;
|
||||
public $lehrauftrag=true;
|
||||
public $lehrveranstaltung_template_id; // integer
|
||||
public $evaluierung=true; // boolean
|
||||
|
||||
|
||||
public $studienplan_lehrveranstaltung_id;
|
||||
@@ -170,6 +171,7 @@ class lehrveranstaltung extends basis_db
|
||||
$this->benotung = $this->db_parse_bool($row->benotung);
|
||||
$this->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$this->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$this->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
// FIXME: LV-Bezeichnung richtig mehrsprachig machen
|
||||
// Zwischenzeitlich 'Italian' zum bezeichnung_arr dazugegeben
|
||||
@@ -244,6 +246,7 @@ class lehrveranstaltung extends basis_db
|
||||
$lv_obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$lv_obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
@@ -394,6 +397,7 @@ class lehrveranstaltung extends basis_db
|
||||
$lv_obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$lv_obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$lv_obj->bezeichnung_arr['Italian'] = $row->bezeichnung;
|
||||
@@ -524,6 +528,7 @@ class lehrveranstaltung extends basis_db
|
||||
$lv_obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$lv_obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
@@ -607,6 +612,7 @@ class lehrveranstaltung extends basis_db
|
||||
$lv_obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$lv_obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
@@ -779,7 +785,7 @@ class lehrveranstaltung extends basis_db
|
||||
insertvon, planfaktor, planlektoren, planpersonalkosten, plankostenprolektor, updateamum, updatevon, sort,
|
||||
zeugnis, projektarbeit, sprache, koordinator, bezeichnung_english, orgform_kurzbz, incoming, lehrtyp_kurzbz, oe_kurzbz,
|
||||
raumtyp_kurzbz, anzahlsemester, semesterwochen, lvnr, semester_alternativ, farbe, lehrveranstaltung_template_id,sws,lvs,alvs,lvps,las,benotung,lvinfo,
|
||||
lehrauftrag, lehrmodus_kurzbz) VALUES ('.
|
||||
lehrauftrag, lehrmodus_kurzbz, evaluierung) VALUES ('.
|
||||
$this->db_add_param($this->studiengang_kz). ', '.
|
||||
$this->db_add_param($this->bezeichnung). ', '.
|
||||
$this->db_add_param($this->kurzbz). ', '.
|
||||
@@ -824,7 +830,8 @@ class lehrveranstaltung extends basis_db
|
||||
$this->db_add_param($this->benotung, FHC_BOOLEAN).','.
|
||||
$this->db_add_param($this->lvinfo, FHC_BOOLEAN).','.
|
||||
$this->db_add_param($this->lehrauftrag, FHC_BOOLEAN).','.
|
||||
$this->db_add_param($this->lehrmodus_kurzbz)
|
||||
$this->db_add_param($this->lehrmodus_kurzbz).','.
|
||||
$this->db_add_param($this->evaluierung, FHC_BOOLEAN)
|
||||
.');';
|
||||
}
|
||||
else
|
||||
@@ -880,7 +887,8 @@ class lehrveranstaltung extends basis_db
|
||||
'las = '.$this->db_add_param($this->las).', '.
|
||||
'benotung = '.$this->db_add_param($this->benotung, FHC_BOOLEAN).', '.
|
||||
'lvinfo = '.$this->db_add_param($this->lvinfo, FHC_BOOLEAN).', '.
|
||||
'lehrauftrag = '.$this->db_add_param($this->lehrauftrag, FHC_BOOLEAN).' '.
|
||||
'lehrauftrag = '.$this->db_add_param($this->lehrauftrag, FHC_BOOLEAN).', '.
|
||||
'evaluierung = '.$this->db_add_param($this->evaluierung, FHC_BOOLEAN).' '.
|
||||
'WHERE lehrveranstaltung_id = ' . $this->db_add_param($this->lehrveranstaltung_id, FHC_INTEGER, false) . ';';
|
||||
}
|
||||
|
||||
@@ -991,6 +999,7 @@ class lehrveranstaltung extends basis_db
|
||||
$lv_obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$lv_obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
@@ -1086,6 +1095,7 @@ class lehrveranstaltung extends basis_db
|
||||
$l->benotung = $this->db_parse_bool($row->benotung);
|
||||
$l->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$l->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$l->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$l->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$l->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
@@ -1170,6 +1180,7 @@ class lehrveranstaltung extends basis_db
|
||||
$lv_obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$lv_obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
@@ -1271,6 +1282,7 @@ class lehrveranstaltung extends basis_db
|
||||
$obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$obj->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
@@ -1396,6 +1408,7 @@ class lehrveranstaltung extends basis_db
|
||||
$obj->lvinfo =$this->db_parse_bool( $lv->lvinfo);
|
||||
$obj->zeugnis = $this->db_parse_bool($lv->zeugnis);
|
||||
$obj->lehrauftrag = $this->db_parse_bool($lv->lehrauftrag);
|
||||
$obj->evaluierung = $this->db_parse_bool($lv->evaluierung);
|
||||
|
||||
$values[] = $obj;
|
||||
|
||||
@@ -1422,6 +1435,7 @@ class lehrveranstaltung extends basis_db
|
||||
$obj->lvinfo =$this->db_parse_bool( $this->lvinfo);
|
||||
$obj->zeugnis = $this->db_parse_bool($this->zeugnis);
|
||||
$obj->lehrauftrag = $this->db_parse_bool($this->lehrauftrag);
|
||||
$obj->evaluierung = $this->db_parse_bool($this->evaluierung);
|
||||
|
||||
$values[] = $obj;
|
||||
}
|
||||
@@ -1476,6 +1490,7 @@ class lehrveranstaltung extends basis_db
|
||||
$obj->export = $lv->export;
|
||||
$obj->genehmigung = $lv->genehmigung;
|
||||
$obj->lehrauftrag = $lv->lehrauftrag;
|
||||
$obj->evaluierung = $lv->evaluierung;
|
||||
$obj->lehre = $lv->lehre;
|
||||
$obj->children = array();
|
||||
if(count($lv->childs) > 0)
|
||||
@@ -1507,6 +1522,7 @@ class lehrveranstaltung extends basis_db
|
||||
$obj->zeugnis = $this->db_parse_bool($this->zeugnis);
|
||||
$obj->curriculum = $this->db_parse_bool($this->curriculum);
|
||||
$obj->lehrauftrag = $this->lehrauftrag;
|
||||
$obj->evaluierung = $this->db_parse_bool($this->evaluierung);
|
||||
|
||||
$values[] = $obj;
|
||||
}
|
||||
@@ -1613,6 +1629,7 @@ class lehrveranstaltung extends basis_db
|
||||
$lv_obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$lv_obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
@@ -1700,6 +1717,7 @@ class lehrveranstaltung extends basis_db
|
||||
$lv_obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$lv_obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
@@ -1873,6 +1891,7 @@ class lehrveranstaltung extends basis_db
|
||||
$lv_obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$lv_obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
@@ -2003,6 +2022,7 @@ class lehrveranstaltung extends basis_db
|
||||
$lv_obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$lv_obj->studiengang_kurzbzlang = $row->studiengang_kurzbzlang;
|
||||
|
||||
@@ -2131,6 +2151,7 @@ class lehrveranstaltung extends basis_db
|
||||
$lv_obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$lv_obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
@@ -2402,6 +2423,7 @@ class lehrveranstaltung extends basis_db
|
||||
$obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$obj->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
|
||||
@@ -63,6 +63,7 @@ class reihungstest extends basis_db
|
||||
|
||||
public $zugangs_ueberpruefung = false; //boolean
|
||||
public $zugangscode; //smallint
|
||||
public $externe_ueberwachung = false; //boolean
|
||||
|
||||
|
||||
/**
|
||||
@@ -119,6 +120,7 @@ class reihungstest extends basis_db
|
||||
$this->aufnahmegruppe_kurzbz = $row->aufnahmegruppe_kurzbz;
|
||||
$this->zugangs_ueberpruefung = $this->db_parse_bool($row->zugangs_ueberpruefung);
|
||||
$this->zugangscode = $row->zugangscode;
|
||||
$this->externe_ueberwachung = $this->db_parse_bool($row->externe_ueberwachung);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -234,7 +236,7 @@ class reihungstest extends basis_db
|
||||
|
||||
$qry = 'BEGIN; INSERT INTO public.tbl_reihungstest (studiengang_kz, ort_kurzbz, anmerkung, datum, uhrzeit,
|
||||
insertamum, insertvon, updateamum, updatevon, max_teilnehmer, oeffentlich, freigeschaltet,
|
||||
studiensemester_kurzbz, stufe, anmeldefrist, aufnahmegruppe_kurzbz, zugangs_ueberpruefung, zugangscode) VALUES('.
|
||||
studiensemester_kurzbz, stufe, anmeldefrist, aufnahmegruppe_kurzbz, zugangs_ueberpruefung, zugangscode, externe_ueberwachung) VALUES('.
|
||||
$this->db_add_param($this->studiengang_kz, FHC_INTEGER).', '.
|
||||
$this->db_add_param($this->ort_kurzbz).', '.
|
||||
$this->db_add_param($this->anmerkung).', '.
|
||||
@@ -250,7 +252,8 @@ class reihungstest extends basis_db
|
||||
$this->db_add_param($this->anmeldefrist).','.
|
||||
$this->db_add_param($this->aufnahmegruppe_kurzbz). ',' .
|
||||
$this->db_add_param($this->zugangs_ueberpruefung, FHC_BOOLEAN).','.
|
||||
$this->db_add_param($this->zugangscode) . ');';
|
||||
$this->db_add_param($this->zugangscode) . ','.
|
||||
$this->db_add_param($this->externe_ueberwachung, FHC_BOOLEAN) . ');';
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -270,7 +273,8 @@ class reihungstest extends basis_db
|
||||
'anmeldefrist='.$this->db_add_param($this->anmeldefrist).', '.
|
||||
'aufnahmegruppe_kurzbz='.$this->db_add_param($this->aufnahmegruppe_kurzbz).', '.
|
||||
'zugangs_ueberpruefung='.$this->db_add_param($this->zugangs_ueberpruefung, FHC_BOOLEAN).', '.
|
||||
'zugangscode='.$this->db_add_param($this->zugangscode).' '.
|
||||
'zugangscode='.$this->db_add_param($this->zugangscode).', '.
|
||||
'externe_ueberwachung='.$this->db_add_param($this->externe_ueberwachung, FHC_BOOLEAN).' '.
|
||||
'WHERE reihungstest_id='.$this->db_add_param($this->reihungstest_id, FHC_INTEGER, false).';';
|
||||
}
|
||||
|
||||
|
||||
@@ -500,6 +500,27 @@ if((!defined('CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN') || CIS_LEHRVERANSTALTU
|
||||
);
|
||||
}
|
||||
|
||||
// LV-Evaluierung NEU
|
||||
if(defined('CIS_LEHRVERANSTALTUNG_EVALUIERUNG_ANZEIGEN')
|
||||
&& CIS_LEHRVERANSTALTUNG_EVALUIERUNG_ANZEIGEN
|
||||
&& $angemeldet
|
||||
&& (!defined('CIS_EVALUIERUNG_ANZEIGEN_STG') || in_array($lv->studiengang_kz, unserialize(CIS_EVALUIERUNG_ANZEIGEN_STG)))
|
||||
&& ($rechte->isBerechtigt('extension/lvevaluierung_init')))
|
||||
{
|
||||
$text='(Pilotphase)';
|
||||
|
||||
$link= APP_ROOT. 'index.ci.php/extensions/FHC-Core-Evaluierung/Initiierung?lehrveranstaltung_id='. urlencode($lv->lehrveranstaltung_id).'&studiensemester_kurzbz='.urlencode($angezeigtes_stsem);
|
||||
|
||||
$menu[]=array
|
||||
(
|
||||
'id'=>'extension_lvevaluierung_menu_initiierung',
|
||||
'position'=>'140',
|
||||
'name'=>$p->t('lvevaluierung/lvevaluierung'). ' - '. strtoupper($p->t('global/neu')),
|
||||
'icon'=>'../../../skin/images/button_lvevaluierung.png',
|
||||
'link'=> $link,
|
||||
'text'=>$text
|
||||
);
|
||||
}
|
||||
|
||||
//************* Menuepunkte anzeigen ****************
|
||||
|
||||
|
||||
@@ -53,6 +53,8 @@ $this->phrasen['testtool/fuerFolgendeStgAngemeldet']='Für folgende Studiengäng
|
||||
$this->phrasen['testtool/invalideGebiete']='Ein oder mehrere Fragengebiet/e inkorrekt!<br>Bitte melden Sie dies der Betreuungsperson.';
|
||||
$this->phrasen['testtool/confirmationText']='<b>Ich bestätige, den Online-Reihungstest persönlich, selbständig, ohne Hilfe einer zusätzlichen Person und ohne Hilfsmittel zu absolvieren.<br>
|
||||
I confirm that I will complete the online placement test personally, independently, without the help of an additional person and without any aids.</b>';
|
||||
$this->phrasen['testtool/dsgvoConfirmText']='<b>Ich habe die <a href ="'. APP_ROOT. 'cms/dms.php?id=373121" target="_blank">Datenschutzerklärung</a> gelesen.</b>';
|
||||
$this->phrasen['testtool/procotoringConfirmText']='<b>Ich stimme der digitalen Beaufsichtigung beim Online-Reihungstest (Proctoring) zu.</b>';
|
||||
$this->phrasen['testtool/loginNoetig']='Bitte beachten Sie, dass der Reihungstest erst <b>unmittelbar</b> vor Ihrem <b>Reihungstesttermin</b> von uns aktiviert wird.<br>
|
||||
Please note that the test will be activated by us <b>immediately</b> before your <b>placement test date</b>.';
|
||||
$this->phrasen['testtool/start']='Reihungstest jetzt starten';
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
/* Repositioning clear icon Datepicker for not being outside the textfield */
|
||||
/* Wrapper */
|
||||
.dp__input_wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* calender-Icon left */
|
||||
.dp__input_icon {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
right: auto;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
/* Clear-Icon right */
|
||||
.dp__clear_icon {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
left: auto;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
/* padding for Icons */
|
||||
.dp__input {
|
||||
padding-left: 36px !important;
|
||||
padding-right: 36px !important;
|
||||
}
|
||||
|
||||
.info-feedback {
|
||||
display: block;
|
||||
font-size: 0.875em;
|
||||
color: #0d6efd; /* Bootstrap primary */
|
||||
}
|
||||
|
||||
.is-info {
|
||||
border-color: #0d6efd;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2026 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 {
|
||||
getTimelocksUser(uid) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Zeitsperren/getZeitsperrenUser/' + uid
|
||||
};
|
||||
},
|
||||
getTypenZeitsperren(){
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Zeitsperren/getTypenZeitsperren/'
|
||||
};
|
||||
},
|
||||
getTypenErreichbarkeit(){
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Zeitsperren/getTypenErreichbarkeit/'
|
||||
};
|
||||
},
|
||||
getStunden(){
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Zeitsperren/getStunden/'
|
||||
};
|
||||
},
|
||||
addZeitsperre(uid, params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Zeitsperren/add/' + uid,
|
||||
params
|
||||
};
|
||||
},
|
||||
editZeitsperre(zeitsperre_id, params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Zeitsperren/update/' + zeitsperre_id,
|
||||
params
|
||||
};
|
||||
},
|
||||
loadZeitsperre(zeitsperre_id) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Zeitsperren/loadZeitsperre/' + zeitsperre_id
|
||||
};
|
||||
},
|
||||
deleteZeitsperre(zeitsperre_id) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Zeitsperren/delete/' + zeitsperre_id
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
export default {
|
||||
getAllStudienSemester(studiensemester=undefined, studiengang=undefined, semester=undefined, studienplan=undefined) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Studium/getAllStudienSemester',
|
||||
params: {studiensemester, studiengang, semester, studienplan}
|
||||
};
|
||||
},
|
||||
getStudiengaengeForStudienSemester(studiensemester) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/Studium/getStudiengaengeForStudienSemester/${studiensemester}`,
|
||||
};
|
||||
},
|
||||
getStudienplaeneBySemester(studiengang, studiensemester) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/Studium/getStudienplaeneBySemester`,
|
||||
params: {
|
||||
studiengang,
|
||||
studiensemester,
|
||||
}
|
||||
};
|
||||
},
|
||||
getLvPlanForStudiensemester(studiensemester_kurzbz, lvid) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/LvPlan/getLvPlanForStudiensemester/${studiensemester}/${lvid}`,
|
||||
};
|
||||
},
|
||||
getLvEvaluierungInfo(studiensemester_kurzbz, lvid) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/Studium/getLvEvaluierungInfo/${studiensemester_kurzbz}/${lvid}`,
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -1,9 +1,9 @@
|
||||
import FhcSearchbar from "../components/searchbar/searchbar.js";
|
||||
import CisMenu from "../components/Cis/Menu.js";
|
||||
import PluginsPhrasen from '../plugins/Phrasen.js';
|
||||
import ApiSearchbar from '../api/factory/searchbar.js';
|
||||
import Theme from "../plugins/Theme.js";
|
||||
|
||||
import FhcBase from '../plugins/FhcBase/FhcBase.js';
|
||||
// import PluginsPhrasen from '../plugins/Phrasen.js';
|
||||
const app = Vue.createApp({
|
||||
name: 'CisApp',
|
||||
components: {
|
||||
@@ -148,6 +148,7 @@ app.use(primevue.config.default, {
|
||||
tooltip: 8000
|
||||
}
|
||||
})
|
||||
app.use(PluginsPhrasen);
|
||||
// app.use(PluginsPhrasen);
|
||||
app.use(FhcBase);
|
||||
app.use(Theme);
|
||||
app.mount('#cis-header');
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import PluginsPhrasen from '../../plugins/Phrasen.js';
|
||||
import {setScrollbarWidth} from "../../helpers/CssVarCalcHelpers.js";
|
||||
import FhcBase from "../../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
const app = Vue.createApp({
|
||||
name: 'DocumentsApp',
|
||||
@@ -89,5 +90,5 @@ const app = Vue.createApp({
|
||||
|
||||
setScrollbarWidth();
|
||||
|
||||
app.use(PluginsPhrasen);
|
||||
app.use(FhcBase);
|
||||
app.mount('#content');
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import ProfilUpdateView from "../../components/Cis/ProfilUpdate/ProfilUpdateView.js";
|
||||
import PluginsPhrasen from "../../plugins/Phrasen.js";
|
||||
|
||||
import ApiProfilUpdate from '../../api/factory/profilUpdate.js';
|
||||
import FhcBase from "../../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
// TODO: sobald in verwendung den vue router pfad zu ProfilUpdateView definieren und diese app in component auslagern
|
||||
const app = Vue.createApp({
|
||||
@@ -34,4 +33,4 @@ const app = Vue.createApp({
|
||||
});
|
||||
},
|
||||
});
|
||||
app.use(PluginsPhrasen).mount("#content");
|
||||
app.use(FhcBase).mount("#content");
|
||||
@@ -1,6 +1,6 @@
|
||||
import {CoreNavigationCmpt} from '../../components/navigation/Navigation.js';
|
||||
import DashboardAdmin from '../../components/Dashboard/Admin.js';
|
||||
import PluginsPhrasen from '../../plugins/Phrasen.js';
|
||||
import FhcBase from "../../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
const app = Vue.createApp({
|
||||
name: 'AdminApp',
|
||||
@@ -12,5 +12,5 @@ const app = Vue.createApp({
|
||||
DashboardAdmin
|
||||
}
|
||||
});
|
||||
app.use(PluginsPhrasen);
|
||||
app.use(FhcBase);
|
||||
app.mount('#main');
|
||||
@@ -1,5 +1,6 @@
|
||||
import FhcDashboard from '../../components/Dashboard/Dashboard.js';
|
||||
import PluginsPhrasen from '../../plugins/Phrasen.js';
|
||||
import FhcBase from '../../plugins/FhcBase/FhcBase.js';
|
||||
|
||||
import Theme from '../../plugins/Theme.js';
|
||||
import contrast from '../../directives/contrast.js';
|
||||
import {setScrollbarWidth} from "../../helpers/CssVarCalcHelpers.js";
|
||||
@@ -16,7 +17,6 @@ import AbgabetoolStudent from "../../components/Cis/Abgabetool/AbgabetoolStudent
|
||||
import AbgabetoolMitarbeiter from "../../components/Cis/Abgabetool/AbgabetoolMitarbeiter.js";
|
||||
import DeadlineOverview from "../../components/Cis/Abgabetool/DeadlineOverview.js";
|
||||
import Studium from "../../components/Cis/Studium/Studium.js";
|
||||
import Zeitsperren from "../../components/Cis/Zeitsperren/Zeitsperren.js";
|
||||
|
||||
import ApiRenderers from '../../api/factory/renderers.js';
|
||||
import ApiRouteInfo from '../../api/factory/routeinfo.js';
|
||||
@@ -217,12 +217,6 @@ const router = VueRouter.createRouter({
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
path: `/Cis/Zeitsperren`,
|
||||
name: 'Zeitsperren',
|
||||
component: Zeitsperren,
|
||||
props: true
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
@@ -337,7 +331,7 @@ app.use(primevue.config.default, {
|
||||
}
|
||||
})
|
||||
app.directive('tooltip', primevue.tooltip);
|
||||
app.use(PluginsPhrasen);
|
||||
app.use(FhcBase);
|
||||
app.use(Theme);
|
||||
app.directive('contrast', contrast);
|
||||
app.mount('#fhccontent');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {CoreNavigationCmpt} from '../components/navigation/Navigation.js';
|
||||
import DashboardAdmin from '../components/Dashboard/Admin.js';
|
||||
import Phrases from "../plugin/Phrasen.js"
|
||||
import FhcBase from "../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
Vue.createApp({
|
||||
name: 'DashboardAdminApp',
|
||||
@@ -13,4 +13,4 @@ Vue.createApp({
|
||||
},
|
||||
mounted() {
|
||||
}
|
||||
}).use(Phrases).mount('#main');
|
||||
}).use(FhcBase).mount('#main');
|
||||
@@ -1,5 +1,5 @@
|
||||
import LVVerwaltung from "../components/LVVerwaltung/LVVerwaltung.js";
|
||||
import Phrasen from "../plugins/Phrasen.js";
|
||||
import FhcBase from "../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
|
||||
|
||||
@@ -98,5 +98,5 @@ app
|
||||
overlay: 1100
|
||||
}
|
||||
})
|
||||
.use(Phrasen)
|
||||
.use(FhcBase)
|
||||
.mount('#main');
|
||||
|
||||
@@ -21,7 +21,7 @@ import {LogsViewerTabulatorEventHandlers} from './TabulatorSetup.js';
|
||||
import {CoreFilterCmpt} from '../../components/filter/Filter.js';
|
||||
import {CoreNavigationCmpt} from '../../components/navigation/Navigation.js';
|
||||
|
||||
import PluginsPhrasen from '../../plugins/Phrasen.js';
|
||||
import FhcBase from "../../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
const logsViewerApp = Vue.createApp({
|
||||
data: function() {
|
||||
@@ -42,5 +42,5 @@ const logsViewerApp = Vue.createApp({
|
||||
}
|
||||
});
|
||||
|
||||
logsViewerApp.use(PluginsPhrasen).mount('#main');
|
||||
logsViewerApp.use(FhcBase).mount('#main');
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//TODO Manu
|
||||
//use this instead of Nachrichten.js
|
||||
import NewMessage from "../../components/Messages/Details/NewMessage/NewDiv.js";
|
||||
import Phrasen from "../../plugin/Phrasen.js";
|
||||
import FhcBase from "../../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
|
||||
|
||||
@@ -23,5 +23,5 @@ app
|
||||
overlay: 1100
|
||||
}
|
||||
})
|
||||
.use(Phrasen)
|
||||
.use(FhcBase)
|
||||
.mount('#main');
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import NewMessage from "../components/Messages/Details/NewMessage/NewDiv.js";
|
||||
|
||||
import Phrasen from "../plugins/Phrasen.js";
|
||||
import FhcBase from "../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
|
||||
|
||||
@@ -23,5 +22,5 @@ app
|
||||
overlay: 1100
|
||||
}
|
||||
})
|
||||
.use(Phrasen)
|
||||
.use(FhcBase)
|
||||
.mount('#main');
|
||||
@@ -16,10 +16,7 @@
|
||||
*/
|
||||
|
||||
import FhcStudentenverwaltung from "../components/Stv/Studentenverwaltung.js";
|
||||
import fhcapifactory from "./api/fhcapifactory.js";
|
||||
|
||||
import PluginsPhrasen from "../plugins/Phrasen.js";
|
||||
|
||||
import FhcBase from "../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
|
||||
|
||||
@@ -217,5 +214,5 @@ app
|
||||
overlay: 1100
|
||||
}
|
||||
})
|
||||
.use(PluginsPhrasen)
|
||||
.use(FhcBase)
|
||||
.mount('#main');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import StudierendenantragAntrag from "../../components/Studierendenantrag/Antrag.js";
|
||||
import StudierendenantragStatus from "../../components/Studierendenantrag/Status.js";
|
||||
import StudierendenantragInfoblock from "../../components/Studierendenantrag/Infoblock.js";
|
||||
import PluginsPhrasen from '../../plugins/Phrasen.js';
|
||||
import FhcBase from "../../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
const app = Vue.createApp({
|
||||
name: 'AntragApp',
|
||||
@@ -21,5 +21,5 @@ const app = Vue.createApp({
|
||||
}
|
||||
});
|
||||
app
|
||||
.use(PluginsPhrasen)
|
||||
.use(FhcBase)
|
||||
.mount('#wrapper');
|
||||
@@ -1,5 +1,5 @@
|
||||
import StudierendenantragLeitung from '../../../components/Studierendenantrag/Leitung.js';
|
||||
import PluginsPhrasen from '../../../plugins/Phrasen.js';
|
||||
import FhcBase from "../../../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
const app = Vue.createApp({
|
||||
name: 'LeitungApp',
|
||||
@@ -8,6 +8,6 @@ const app = Vue.createApp({
|
||||
}
|
||||
});
|
||||
app
|
||||
.use(PluginsPhrasen)
|
||||
.use(FhcBase)
|
||||
.use(primevue.config.default,{zIndex: {overlay: 9999}})
|
||||
.mount('#wrapper');
|
||||
@@ -1,5 +1,5 @@
|
||||
import LvZuweisung from '../../../components/Studierendenantrag/Lvzuweisung.js';
|
||||
import PluginsPhrasen from '../../../plugins/Phrasen.js';
|
||||
import FhcBase from "../../../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
const app = Vue.createApp({
|
||||
name: 'LvzuweisungApp',
|
||||
@@ -13,5 +13,5 @@ const app = Vue.createApp({
|
||||
}
|
||||
});
|
||||
app
|
||||
.use(PluginsPhrasen)
|
||||
.use(FhcBase)
|
||||
.mount('#wrapper');
|
||||
@@ -1,5 +1,5 @@
|
||||
import LvPopup from '../../../components/Studierendenantrag/Leitung/LvPopup.js';
|
||||
import PluginsPhrasen from '../../../plugins/Phrasen.js';
|
||||
import FhcBase from "../../../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
const app = Vue.createApp({
|
||||
name: 'StudentApp',
|
||||
@@ -8,5 +8,5 @@ const app = Vue.createApp({
|
||||
}
|
||||
});
|
||||
app
|
||||
.use(PluginsPhrasen)
|
||||
.use(FhcBase)
|
||||
.mount('#wrapper');
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
import LvTemplateUebersicht from '../../../lehre/lvplanung/LvTemplateUebersicht.js';
|
||||
import {CoreNavigationCmpt} from '../../../components/navigation/Navigation.js';
|
||||
import PluginsPhrasen from "../../../plugins/Phrasen.js";
|
||||
import FhcBase from "../../../plugins/FhcBase/FhcBase.js";
|
||||
|
||||
|
||||
const lvTemplatesApp = Vue.createApp({
|
||||
@@ -30,5 +30,5 @@ const lvTemplatesApp = Vue.createApp({
|
||||
|
||||
lvTemplatesApp
|
||||
.use(primevue.config.default,{zIndex: {overlay: 9999}})
|
||||
.use(PluginsPhrasen)
|
||||
.use(FhcBase)
|
||||
.mount('#main')
|
||||
@@ -8,12 +8,6 @@ export const FhcChart = {
|
||||
},
|
||||
template: `
|
||||
<div style="width:100%;height:100%;overflow:auto">
|
||||
<div role="group" aria-label="Chart Modus">
|
||||
<Button :class="(chartOptions.chart.type === 'pie' ? 'active ' : '') + 'btn btn-outline-secondary'" style="width: 48px;" @click="chartOptions.chart.type='pie'"><i class="fa-solid fa-chart-pie"></i></Button>
|
||||
<Button :class="(chartOptions.chart.type === 'bar' ? 'active ' : '') + 'btn btn-outline-secondary'" style="width: 48px;" @click="chartOptions.chart.type='bar'"><i class="fa-solid fa-chart-bar"></i></Button>
|
||||
<Button :class="(chartOptions.chart.type === 'column' ? 'active ' : '') + 'btn btn-outline-secondary'" style="width: 48px;" @click="chartOptions.chart.type='column'"><i class="fa-solid fa-chart-simple"></i></Button>
|
||||
<Button :class="(chartOptions.chart.type === 'line' ? 'active ' : '') + 'btn btn-outline-secondary'" style="width: 48px;" @click="chartOptions.chart.type='line'"><i class="fa-solid fa-chart-line"></i></Button>
|
||||
</div>
|
||||
<figure>
|
||||
<highcharts class="chart" :options="chartOptions"></highcharts>
|
||||
</figure>
|
||||
|
||||
@@ -3,7 +3,6 @@ import FhcSearchbar from "../searchbar/searchbar.js";
|
||||
import CisSprachen from "./Sprachen.js"
|
||||
import ThemeSwitch from "./ThemeSwitch.js";
|
||||
import ApiCisMenu from '../../api/factory/cis/menu.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CisMenuEntry,
|
||||
|
||||
@@ -2,9 +2,10 @@ import BsModal from "../../Bootstrap/Modal.js";
|
||||
import LvMenu from "./LvMenu.js";
|
||||
|
||||
import ApiAddons from '../../../api/factory/addons.js';
|
||||
import ApiStudium from '../../../api/factory/studium.js';
|
||||
|
||||
export default {
|
||||
|
||||
name: "LvUebersicht",
|
||||
props:{
|
||||
event:{
|
||||
type:Object,
|
||||
@@ -63,7 +64,7 @@ export default {
|
||||
|
||||
// check lv evaluierung info
|
||||
if (this.studium_studiensemester) {
|
||||
this.$fhcApi.factory.studium.getLvEvaluierungInfo(this.studium_studiensemester, this.event.lehreinheit_id ?? this.event.lehrveranstaltung_id)
|
||||
this.$api.call(ApiStudium.getLvEvaluierungInfo(this.studium_studiensemester, this.event.lehreinheit_id ?? this.event.lehrveranstaltung_id))
|
||||
.then(data => data.data)
|
||||
.then(res => {
|
||||
this.lvEvaluierungMessage = res.message;
|
||||
@@ -72,7 +73,7 @@ export default {
|
||||
|
||||
// check if the lv has lvplan entries for this studiensemester
|
||||
if (this.studiensemester && this.event) {
|
||||
return this.$fhcApi.factory.studium.getLvPlanForStudiensemester(this.studiensemester, this.event.lehreinheit_id ?? this.event.lehrveranstaltung_id)
|
||||
this.$api.call(ApiStudium.getLvPlanForStudiensemester(this.studiensemester, this.event.lehreinheit_id ?? this.event.lehrveranstaltung_id))
|
||||
.then(data => data.data)
|
||||
.then(res => {
|
||||
if (Array.isArray(res) && res.length > 0) {
|
||||
|
||||
@@ -31,7 +31,7 @@ export default {
|
||||
this.event.lektor.slice(0, 3).map(lektor => lektor.kurzbz).join("\n")
|
||||
+ "\n" + this.$p.t('lehre/weitereLektoren', [this.event.lektor.length - 3])
|
||||
].join(": "));
|
||||
} else {console.log(this.event.lektor);
|
||||
} else {
|
||||
tooltipArray.push([
|
||||
this.$p.t('lehre/lektor'),
|
||||
this.event.lektor.map(lektor => lektor.kurzbz).join("\n")
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import LvUebersicht from "../Mylv/LvUebersicht.js";
|
||||
|
||||
import ApiStudium from '../../../api/factory/studium.js';
|
||||
|
||||
export default {
|
||||
name: "Studium",
|
||||
data(){
|
||||
return {
|
||||
studienSemester :[],
|
||||
@@ -97,28 +98,28 @@ export default {
|
||||
return value;
|
||||
},
|
||||
changeSelectedStudienSemester(studiensemester_kurzbz) {
|
||||
this.$fhcApi.factory.studium.getAllStudienSemester(studiensemester_kurzbz, this.selectedStudiengang, this.selectedSemester, this.selectedStudienordnung)
|
||||
this.$api.call(ApiStudium.getAllStudienSemester(studiensemester_kurzbz, this.selectedStudiengang, this.selectedSemester, this.selectedStudienordnung))
|
||||
.then(data => data.data)
|
||||
.then(res => {
|
||||
this.extractPropertyValues(res);
|
||||
})
|
||||
},
|
||||
changeSelectedStudienGang(studiengang_kz) {
|
||||
this.$fhcApi.factory.studium.getAllStudienSemester(this.selectedStudiensemester, studiengang_kz, this.selectedSemester, this.selectedStudienordnung)
|
||||
this.$api.call(ApiStudium.getAllStudienSemester(this.selectedStudiensemester, studiengang_kz, this.selectedSemester, this.selectedStudienordnung))
|
||||
.then(data => data.data)
|
||||
.then(res => {
|
||||
this.extractPropertyValues(res);
|
||||
})
|
||||
},
|
||||
changeSelectedSemester(semester) {
|
||||
this.$fhcApi.factory.studium.getAllStudienSemester(this.selectedStudiensemester, this.selectedStudiengang, semester, this.selectedStudienordnung)
|
||||
this.$api.call(ApiStudium.getAllStudienSemester(this.selectedStudiensemester, this.selectedStudiengang, semester, this.selectedStudienordnung))
|
||||
.then(data => data.data)
|
||||
.then(res => {
|
||||
this.extractPropertyValues(res);
|
||||
})
|
||||
},
|
||||
changeSelectedStudienPlan(studienplan_id) {
|
||||
this.$fhcApi.factory.studium.getAllStudienSemester(this.selectedStudiensemester, this.selectedStudiengang, this.selectedSemester, studienplan_id)
|
||||
this.$api.call(ApiStudium.getAllStudienSemester(this.selectedStudiensemester, this.selectedStudiengang, this.selectedSemester, studienplan_id))
|
||||
.then(data => data.data)
|
||||
.then(res => {
|
||||
this.extractPropertyValues(res);
|
||||
@@ -256,8 +257,8 @@ export default {
|
||||
const studienordnung = JSON.parse(this.getDataFromLocalStorage("studienordnung")) ?? undefined;
|
||||
|
||||
// only fetch default data if no data is stored in the local storage
|
||||
|
||||
this.$fhcApi.factory.studium.getAllStudienSemester(studiensemester, studiengang, semester, studienordnung)
|
||||
|
||||
this.$api.call(ApiStudium.getAllStudienSemester(studiensemester, studiengang, semester, studienordnung))
|
||||
.then(data => data.data)
|
||||
.then(res => {
|
||||
this.extractPropertyValues(res);
|
||||
|
||||
@@ -1,673 +0,0 @@
|
||||
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 ApiAuthinfo from '../../../api/factory/authinfo.js';
|
||||
import ApiTimelocks from "../../../api/factory/cis/zeitsperren.js";
|
||||
import ApiStvAbschlusspruefung from "../../../api/factory/stv/abschlusspruefung.js";
|
||||
|
||||
export default {
|
||||
name: 'ZeitsperrenComponent',
|
||||
components: {
|
||||
CoreFilterCmpt,
|
||||
FormForm,
|
||||
FormInput,
|
||||
PvAutoComplete
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
uid: null,
|
||||
statusNew: true,
|
||||
timeRecordingLockedUntil: '2015-08-31', //TODO(Manu) check if needed
|
||||
typesTimeLocks: ["Urlaub", "PflegeU", "ZA", "Krank", "DienstF", "DienstV", "CovidSB", "CovidKS"],
|
||||
typesHideStunden: ["Urlaub", "ZA", "Krank", "DienstF", "DienstV", "CovidSB", "CovidKS"],
|
||||
listTypenZeitsperren: [],
|
||||
listTypenErreichbarkeit: [],
|
||||
listStunden: [],
|
||||
tabulatorOptions: null,
|
||||
tabulatorEvents: [],
|
||||
originalData: {},
|
||||
zeitsperreData: {
|
||||
vondatum : new Date(),
|
||||
bisdatum: new Date(),
|
||||
vonISO : "00:00:00", //later
|
||||
bisISO: "23:59:59", //later
|
||||
erreichbarkeit_kurzbz: 'n',
|
||||
zeitsperretyp_kurzbz: 'Arzt',
|
||||
vonstunde: null,
|
||||
bisstunde: null
|
||||
},
|
||||
changedData: {},
|
||||
selectedVertretung: null,
|
||||
filteredMitarbeiter: [],
|
||||
abortController: {
|
||||
mitarbeiter: null
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
dienstverhinderungen() {
|
||||
return {
|
||||
"Eheschließung": "a) " + this.$p.t('zeitsperren', 'eheschliessung'),
|
||||
"Geburt eigenes Kind": "b) " + this.$p.t('zeitsperren', 'geburt'),
|
||||
"Heirat Kind/Geschwister": "c) " + this.$p.t('zeitsperren', 'heirat'),
|
||||
"Eigene Sponsion/Promotion": "d) " + this.$p.t('zeitsperren', 'sponsion'),
|
||||
"Lebensbedr. Erkrankung P/K/E": "e) " + this.$p.t('zeitsperren', 'erkrankung_lebensbedr'),
|
||||
"Ableben P/K/E": "f) " + this.$p.t('zeitsperren', 'ableben'),
|
||||
"Bestattung G/S/G": "g) " + this.$p.t('zeitsperren', 'bestattung'),
|
||||
"Wohnungswechsel": "h) " + this.$p.t('zeitsperren', 'umzug'),
|
||||
"Bundesheer": "i) " + this.$p.t('zeitsperren', 'bundesheer'),
|
||||
"Volksschultag": "j) " + this.$p.t('zeitsperren', 'volksschultag')};
|
||||
},
|
||||
showInfo(){
|
||||
return this.zeitsperreData.zeitsperretyp_kurzbz === 'DienstF';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
actionEditZeitsperre(zeitsperre_id){
|
||||
this.statusNew = false;
|
||||
return this.$api
|
||||
.call(ApiTimelocks.loadZeitsperre(zeitsperre_id))
|
||||
.then(response => {
|
||||
this.originalData = structuredClone(response.data);
|
||||
this.zeitsperreData = structuredClone(response.data);
|
||||
|
||||
this.selectedVertretung = {
|
||||
label: this.getPersonLabel(this.zeitsperreData.ma_titelpre, this.zeitsperreData.ma_nachname, this.zeitsperreData.ma_vorname, this.zeitsperreData.ma_titelpost, this.zeitsperreData.vertretung_uid),
|
||||
person_id: this.zeitsperreData.ma_person_id,
|
||||
mitarbeiter_uid: this.zeitsperreData.vertretung_uid
|
||||
};
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
actionDeleteZeitsperre(zeitsperre_id){
|
||||
this.$fhcAlert
|
||||
.confirmDelete()
|
||||
.then(result => result
|
||||
? zeitsperre_id
|
||||
: Promise.reject({ handled: true })
|
||||
)
|
||||
.then(() => this.deleteZeitsperre(zeitsperre_id))
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
saveZeitsperre(zeitsperreId = null) {
|
||||
const isNew = !zeitsperreId;
|
||||
|
||||
let payload = isNew
|
||||
? { ...this.zeitsperreData } // add
|
||||
: this.getChangedFields(this.originalData, // edit
|
||||
this.zeitsperreData);
|
||||
|
||||
if (!isNew && Object.keys(payload).length === 0) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const request = isNew
|
||||
? ApiTimelocks.addZeitsperre(this.uid, payload)
|
||||
: ApiTimelocks.editZeitsperre(zeitsperreId, payload);
|
||||
|
||||
return this.$refs.dataZeitsperre
|
||||
.call(request)
|
||||
.then(() => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
|
||||
|
||||
this.reset();
|
||||
this.reload();
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
deleteZeitsperre(zeitsperre_id){
|
||||
return this.$api
|
||||
.call(ApiTimelocks.deleteZeitsperre(zeitsperre_id))
|
||||
.then(response => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError)
|
||||
.finally(()=> {
|
||||
this.reload();
|
||||
});
|
||||
},
|
||||
searchMitarbeiter(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 = [];
|
||||
for (let mitarbeiter of result.data.retval) {
|
||||
this.filteredMitarbeiter.push(
|
||||
{
|
||||
label: this.getPersonLabel(
|
||||
mitarbeiter.titelpre,
|
||||
mitarbeiter.nachname,
|
||||
mitarbeiter.vorname,
|
||||
mitarbeiter.titelpost,
|
||||
mitarbeiter.mitarbeiter_uid
|
||||
),
|
||||
person_id: mitarbeiter.person_id,
|
||||
mitarbeiter_uid: mitarbeiter.mitarbeiter_uid
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
getPersonLabel(titelpre, nachname, vorname, titelpost, uid) {
|
||||
if(!uid)
|
||||
return '';
|
||||
return nachname + ' ' + vorname + (titelpre ? ' ' + titelpre : '') + (titelpost ? ' ' + titelpost : '') + (uid ? ' (' + uid + ')' : '');
|
||||
},
|
||||
reload() {
|
||||
if (this.$refs.table)
|
||||
this.$refs.table.reloadTable();
|
||||
},
|
||||
reset(){
|
||||
this.statusNew = true;
|
||||
this.selectedVertretung = null;
|
||||
this.zeitsperreData = {
|
||||
vondatum : new Date(),
|
||||
bisdatum: new Date(),
|
||||
vonISO : "00:00:00", //later
|
||||
bisISO: "23:59:59", //later
|
||||
erreichbarkeit_kurzbz: 'n',
|
||||
zeitsperretyp_kurzbz: 'Arzt',
|
||||
vonstunde: null,
|
||||
bisstunde: null
|
||||
};
|
||||
this.originalData = {};
|
||||
},
|
||||
handleChangeVonStunde(){
|
||||
let stunde = this.zeitsperreData.vonstunde;
|
||||
const result = this.listStunden.find(item => item.stunde === stunde);
|
||||
if (!result) {
|
||||
this.zeitsperreData.vonISO = '00:00:00';
|
||||
return;
|
||||
}
|
||||
this.zeitsperreData.vonISO = result.beginn;
|
||||
},
|
||||
handleChangeBisStunde(){
|
||||
let stunde = this.zeitsperreData.bisstunde;
|
||||
const result = this.listStunden.find(item => item.stunde === stunde);
|
||||
if (!result) {
|
||||
this.zeitsperreData.bisISO = '23:59:59';
|
||||
return;
|
||||
}
|
||||
this.zeitsperreData.bisISO = result.ende;
|
||||
},
|
||||
handleStunden(){
|
||||
if (this.typesHideStunden.includes(this.zeitsperreData.zeitsperretyp_kurzbz)){
|
||||
this.zeitsperreData.vonstunde = null;
|
||||
this.zeitsperreData.bisstunde = null;
|
||||
this.zeitsperreData.vonISO = '00:00:00';
|
||||
this.zeitsperreData.bisISO = '23:59:59';
|
||||
}
|
||||
},
|
||||
copyDateForBis(){
|
||||
this.zeitsperreData.bisdatum = this.zeitsperreData.vondatum;
|
||||
},
|
||||
getChangedFields(original, current) {
|
||||
const diff = {};
|
||||
|
||||
Object.keys(current).forEach((key) => {
|
||||
if (current[key] !== original[key]) {
|
||||
diff[key] = current[key];
|
||||
}
|
||||
});
|
||||
return diff;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedVertretung(newVal) {
|
||||
this.zeitsperreData.vertretung_uid = newVal?.mitarbeiter_uid || null;
|
||||
},
|
||||
'zeitsperreData.zeitsperretyp_kurzbz'(newVal) {
|
||||
if (newVal === 'DienstV') {
|
||||
// set first key as default
|
||||
if (!this.zeitsperreData.bezeichnung) {
|
||||
const firstKey = Object.keys(this.dienstverhinderungen)[0];
|
||||
this.zeitsperreData.bezeichnung = firstKey;
|
||||
}
|
||||
} else {
|
||||
this.zeitsperreData.bezeichnung = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$api.call(ApiAuthinfo.getAuthUID()).then(res => {
|
||||
|
||||
//check if there is a user, passed via route
|
||||
const urlUid = this.$route?.query?.uid;
|
||||
this.uid = urlUid ? urlUid : res.data.uid;
|
||||
|
||||
this.tabulatorOptions = {
|
||||
ajaxURL: 'dummy',
|
||||
ajaxRequestFunc: () =>
|
||||
this.$api.call(ApiTimelocks.getTimelocksUser(this.uid)),
|
||||
ajaxResponse: (url, params, response) => response.data,
|
||||
columns: [
|
||||
{title:"bezeichnung", field:"bezeichnung"},
|
||||
{title:"Grund", field:"beschreibung"},
|
||||
{title:"Von", field:"vondatum",
|
||||
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",
|
||||
});
|
||||
}
|
||||
},
|
||||
{title:"Bis", field:"bisdatum",
|
||||
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",
|
||||
});
|
||||
}
|
||||
},
|
||||
{title:"vonstunde", field:"vonstunde", visible: false},
|
||||
{title:"bisstunde", field:"bisstunde", visible: false},
|
||||
{title:"Vertretung", field:"vertretung"},
|
||||
{title:"Erreichbarkeit", field:"erreichbarkeit_beschreibung"},
|
||||
{title:"zeitsperre_id", field:"zeitsperre_id", visible: false},
|
||||
{title:"mitarbeiter_uid", field:"mitarbeiter_uid", visible: false},
|
||||
{title:"freigabeamum", field:"freigabeamum", visible: false,
|
||||
formatter: function (cell) {
|
||||
const value = cell.getValue();
|
||||
return value === null
|
||||
? ''
|
||||
: '<i class="fa fa-check text-success"></i>';
|
||||
}
|
||||
},
|
||||
{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.actionEditZeitsperre(cell.getData().zeitsperre_id)
|
||||
);
|
||||
if(cell.getData().zeitsperretyp_kurzbz == 'DienstV' || cell.getData().zeitsperretyp_kurzbz == 'ZVerfueg'){
|
||||
button.disabled = true;
|
||||
}
|
||||
//TODO(Manu) check if needed
|
||||
if(this.typesTimeLocks.includes(cell.getData().zeitsperretyp_kurzbz) && (cell.getData().vondatum < this.timeRecordingLockedUntil)){
|
||||
button.disabled = true;
|
||||
}
|
||||
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.deleteZeitsperre(cell.getData().zeitsperre_id)
|
||||
this.actionDeleteZeitsperre(cell.getData().zeitsperre_id)
|
||||
);
|
||||
if(cell.getData().zeitsperretyp_kurzbz == 'Urlaub' || cell.getData().zeitsperretyp_kurzbz == 'ZVerfueg'){
|
||||
button.disabled = true;
|
||||
}
|
||||
//TODO(Manu) check if needed
|
||||
if(this.typesTimeLocks.includes(cell.getData().zeitsperretyp_kurzbz) && (cell.getData().vondatum < this.timeRecordingLockedUntil)){
|
||||
button.disabled = true;
|
||||
}
|
||||
container.append(button);
|
||||
|
||||
return container;
|
||||
},
|
||||
frozen: true
|
||||
},
|
||||
]
|
||||
};
|
||||
this.tabulatorEvents = [
|
||||
{
|
||||
event: 'tableBuilt',
|
||||
handler: async() => {
|
||||
await this.$p.loadCategory(['global', 'person', 'zeitsperren', 'ui', 'abschlusspruefung']);
|
||||
|
||||
let cm = this.$refs.table.tabulator.columnManager;
|
||||
|
||||
cm.getColumnByField('bezeichnung').component.updateDefinition({
|
||||
title: this.$p.t('person', 'grund')
|
||||
});
|
||||
cm.getColumnByField('beschreibung').component.updateDefinition({
|
||||
title: this.$p.t('global', 'bezeichnung')
|
||||
});
|
||||
cm.getColumnByField('vondatum').component.updateDefinition({
|
||||
title: this.$p.t('ui', 'von')
|
||||
});
|
||||
cm.getColumnByField('bisdatum').component.updateDefinition({
|
||||
title: this.$p.t('global', 'bis')
|
||||
});
|
||||
cm.getColumnByField('vonstunde').component.updateDefinition({
|
||||
title: this.$p.t('zeitsperren', 'stunde_von')
|
||||
});
|
||||
cm.getColumnByField('bisstunde').component.updateDefinition({
|
||||
title: this.$p.t('zeitsperren', 'stunde_bis')
|
||||
});
|
||||
cm.getColumnByField('vertretung').component.updateDefinition({
|
||||
title: this.$p.t('person', 'vertretung')
|
||||
});
|
||||
|
||||
cm.getColumnByField('erreichbarkeit_beschreibung').component.updateDefinition({
|
||||
title: this.$p.t('person', 'erreichbarkeit')
|
||||
});
|
||||
cm.getColumnByField('freigabeamum').component.updateDefinition({
|
||||
title: this.$p.t('abschlusspruefung', 'freigabe')
|
||||
});
|
||||
|
||||
/* cm.getColumnByField('actions').component.updateDefinition({
|
||||
title: this.$p.t('global', 'aktionen')
|
||||
});*/
|
||||
|
||||
}
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
this.$api
|
||||
.call(ApiTimelocks.getTypenZeitsperren())
|
||||
.then(result => {
|
||||
this.listTypenZeitsperren = result.data;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
this.$api
|
||||
.call(ApiTimelocks.getTypenErreichbarkeit())
|
||||
.then(result => {
|
||||
this.listTypenErreichbarkeit = result.data;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
this.$api
|
||||
.call(ApiTimelocks.getStunden())
|
||||
.then(result => {
|
||||
this.listStunden = result.data;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
},
|
||||
template: /* html */`
|
||||
<div class="zeitsperre">
|
||||
<h4>{{$p.t('zeitsperren', 'header_zeitsperren')}} ({{uid}}) </h4>
|
||||
|
||||
<form-form class="row g-3 mt-3" ref="dataZeitsperre">
|
||||
<div class= "w-50">
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
type="select"
|
||||
:class="showInfo ? 'is-info' : ''"
|
||||
name="zeitsperretyp_kurzbz"
|
||||
:label="$p.t('person/grund')"
|
||||
v-model="zeitsperreData.zeitsperretyp_kurzbz"
|
||||
@change="handleStunden"
|
||||
>
|
||||
<option
|
||||
v-for="typ in listTypenZeitsperren"
|
||||
:key="typ.zeitsperretyp_kurzbz"
|
||||
:value="typ.zeitsperretyp_kurzbz"
|
||||
:disabled="typ.zeitsperretyp_kurzbz == 'Urlaub'"
|
||||
>
|
||||
{{typ.beschreibung}}
|
||||
</option>
|
||||
</form-input>
|
||||
<div v-if="showInfo" class="info-feedback">
|
||||
<strong> Dienstfreistellungen</strong> nur in Absprache mit HR Service eintragen!
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="zeitsperreData.zeitsperretyp_kurzbz == 'DienstV'" class="row mb-3">
|
||||
<form-input
|
||||
type="select"
|
||||
name="beschreibung"
|
||||
:label="$p.t('ui/bezeichnung')"
|
||||
v-model="zeitsperreData.bezeichnung"
|
||||
>
|
||||
<option v-for="(beschreibung, key) in dienstverhinderungen"
|
||||
:key="key"
|
||||
:value="key">{{beschreibung}}
|
||||
</option>
|
||||
|
||||
</form-input>
|
||||
</div>
|
||||
<div v-else class="row mb-3">
|
||||
<form-input
|
||||
type="text"
|
||||
name="beschreibung"
|
||||
:label="$p.t('ui/bezeichnung')"
|
||||
v-model="zeitsperreData.bezeichnung"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="mb-3 col-2">
|
||||
<form-input
|
||||
type="DatePicker"
|
||||
name="vondatum"
|
||||
:label="$p.t('ui/from')"
|
||||
v-model="zeitsperreData.vondatum"
|
||||
auto-apply
|
||||
:enable-time-picker="false"
|
||||
format="dd.MM.yyyy"
|
||||
text-input
|
||||
preview-format="dd.MM.yyyy"
|
||||
:teleport="true"
|
||||
required
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="mb-3 col-1 d-flex align-items-end">
|
||||
<button
|
||||
class="btn btn-outline-secondary"
|
||||
title="Für Bis-Datum übernehmen"
|
||||
@click.prevent="copyDateForBis"
|
||||
>
|
||||
<i class="fa-solid fa-arrow-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 col-3">
|
||||
<form-input
|
||||
v-if="!typesHideStunden.includes(zeitsperreData.zeitsperretyp_kurzbz)"
|
||||
type="select"
|
||||
name="vonstunde"
|
||||
:label="$p.t('zeitsperren/stunde')"
|
||||
v-model="zeitsperreData.vonstunde"
|
||||
@change="handleChangeVonStunde"
|
||||
>
|
||||
<option value='null'>*</option>
|
||||
<option
|
||||
v-for="std in listStunden"
|
||||
:key="std.stunde"
|
||||
:value="std.stunde"
|
||||
>
|
||||
{{std.stunde}} ({{std.beginn}} - {{std.ende}})
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Uncomment to use timestamp VON
|
||||
<div class="mb-3 col-3">
|
||||
<form-input
|
||||
type="text"
|
||||
name="vonISO"
|
||||
label="vonISO"
|
||||
v-model="zeitsperreData.vonISO"
|
||||
auto-apply
|
||||
:enable-time-picker="true"
|
||||
format="dd.MM.yyyy HH:mm"
|
||||
text-input
|
||||
preview-format="dd.MM.yyyy HH:mm"
|
||||
:teleport="true"
|
||||
>
|
||||
{{timestampHoursVon}}
|
||||
</form-input>
|
||||
</div>
|
||||
-->
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="mb-3 col-2">
|
||||
<form-input
|
||||
type="DatePicker"
|
||||
name="bisdatum"
|
||||
:label="$p.t('global/bis')"
|
||||
v-model="zeitsperreData.bisdatum"
|
||||
auto-apply
|
||||
:enable-time-picker="false"
|
||||
format="dd.MM.yyyy"
|
||||
text-input
|
||||
preview-format="dd.MM.yyyy"
|
||||
:teleport="true"
|
||||
required
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="mb-3 col-1"></div>
|
||||
|
||||
<div class="mb-3 col-3">
|
||||
<form-input
|
||||
v-if="!typesHideStunden.includes(zeitsperreData.zeitsperretyp_kurzbz)"
|
||||
type="select"
|
||||
name="bisstunde"
|
||||
:label="$p.t('zeitsperren/stunde')"
|
||||
v-model="zeitsperreData.bisstunde"
|
||||
@change="handleChangeBisStunde"
|
||||
>
|
||||
<option value='null'>*</option>
|
||||
<option
|
||||
v-for="std in listStunden"
|
||||
:key="std.stunde"
|
||||
:value="std.stunde"
|
||||
>
|
||||
{{std.stunde}} ({{std.beginn}} - {{std.ende}})
|
||||
</option>
|
||||
</form-input>
|
||||
</div>
|
||||
|
||||
<!-- Uncomment to use timestamp BIS
|
||||
<div class="mb-3 col-3">
|
||||
<form-input
|
||||
type="text"
|
||||
name="bisISO"
|
||||
label="bisISO"
|
||||
v-model="zeitsperreData.bisISO"
|
||||
auto-apply
|
||||
:enable-time-picker="true"
|
||||
format="dd.MM.yyyy HH:mm"
|
||||
text-input
|
||||
preview-format="dd.MM.yyyy HH:mm"
|
||||
:teleport="true"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
-->
|
||||
|
||||
</div>
|
||||
|
||||
<div class= "w-50">
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
type="autocomplete"
|
||||
name="vertretung_uid"
|
||||
:label="$p.t('person/vertretung')"
|
||||
v-model="selectedVertretung"
|
||||
optionLabel="label"
|
||||
optionValue="mitarbeiter_uid"
|
||||
dropdown
|
||||
forceSelection
|
||||
:suggestions="filteredMitarbeiter"
|
||||
@complete="searchMitarbeiter"
|
||||
:min-length="3"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row align-items-end">
|
||||
<div class="mb-3 col-4">
|
||||
<form-input
|
||||
type="select"
|
||||
name="erreichbarkeit"
|
||||
:label="$p.t('person/erreichbarkeit')"
|
||||
v-model="zeitsperreData.erreichbarkeit_kurzbz"
|
||||
>
|
||||
<option
|
||||
v-for="typ in listTypenErreichbarkeit"
|
||||
:key="typ.erreichbarkeit_kurzbz"
|
||||
:value="typ.erreichbarkeit_kurzbz"
|
||||
>
|
||||
{{typ.beschreibung}}
|
||||
</option>
|
||||
</form-input>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 col-3">
|
||||
<button
|
||||
v-if="statusNew"
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="saveZeitsperre()">
|
||||
{{$p.t('zeitsperren', 'addZeitsperre')}}
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
type="button"
|
||||
class="btn btn-warning"
|
||||
@click="saveZeitsperre(zeitsperreData.zeitsperre_id)">
|
||||
{{$p.t('zeitsperren', 'saveZeitsperre')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</form-form>
|
||||
|
||||
<div class="d-flex align-items-start text-muted small">
|
||||
<i class="fa fa-circle-info me-2 mt-1"></i>
|
||||
<div>
|
||||
<strong>{{$p.t('alert', 'attention')}}</strong><br>
|
||||
{{$p.t('zeitsperren', 'info_zeitsperrenMoreDays')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
<core-filter-cmpt
|
||||
v-if="tabulatorOptions"
|
||||
ref="table"
|
||||
:tabulator-options="tabulatorOptions"
|
||||
:tabulator-events="tabulatorEvents"
|
||||
table-only
|
||||
:side-menu="false"
|
||||
reload
|
||||
:reload-btn-infotext="this.$p.t('table', 'reload')"
|
||||
>
|
||||
</core-filter-cmpt>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -280,6 +280,7 @@ export default {
|
||||
<template #chip="data"><slot name="chip" v-bind="data"></slot></template>
|
||||
<template #header="data"><slot name="header" v-bind="data"></slot></template>
|
||||
<template #footer="data"><slot name="footer" v-bind="data"></slot></template>
|
||||
<template #selectedItem="data"><slot name="selectedItem" v-bind="data"></slot></template>
|
||||
<template #option="data"><slot name="option" v-bind="data"></slot></template>
|
||||
<template #optiongroup="data"><slot name="optiongroup" v-bind="data"></slot></template>
|
||||
<template #content="data"><slot name="content" v-bind="data"></slot></template>
|
||||
|
||||
@@ -42,7 +42,11 @@ export default {
|
||||
showErweitert: Boolean,
|
||||
showDocument: Boolean,
|
||||
showTinyMce: Boolean,
|
||||
visibleColumns: Array
|
||||
visibleColumns: Array,
|
||||
tabulatorPersistenceId: {
|
||||
type: String,
|
||||
default: 'core-notiz'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -179,7 +183,15 @@ export default {
|
||||
//responsiveLayout: "collapse",
|
||||
maxHeight: '200px',
|
||||
index: 'notiz_id',
|
||||
persistenceID: 'core-notiz'
|
||||
persistenceID: this.tabulatorPersistenceId,
|
||||
persistence: {
|
||||
sort: false,
|
||||
columns: ["width", "visible", "frozen"],
|
||||
filter: false,
|
||||
headerFilter: false,
|
||||
group: false,
|
||||
page: false,
|
||||
}
|
||||
},
|
||||
tabulatorEvents: [
|
||||
{
|
||||
|
||||
+2
@@ -757,6 +757,7 @@ export default {
|
||||
:label="$p.t('global', 'datum')"
|
||||
type="DatePicker"
|
||||
v-model="formData.datum"
|
||||
model-type="yyyy-MM-dd"
|
||||
auto-apply
|
||||
:enable-time-picker="false"
|
||||
text-input
|
||||
@@ -781,6 +782,7 @@ export default {
|
||||
:label="$p.t('abschlusspruefung', 'sponsion')"
|
||||
type="DatePicker"
|
||||
v-model="formData.sponsion"
|
||||
model-type="yyyy-MM-dd"
|
||||
auto-apply
|
||||
:enable-time-picker="false"
|
||||
text-input
|
||||
|
||||
@@ -31,6 +31,7 @@ export default {
|
||||
show-tiny-mce
|
||||
:visibleColumns="['titel','text','verfasser','bearbeiter','dokumente']"
|
||||
@reload="$emit('update:suffix')"
|
||||
tabulator-persistence-id="stv-notiz-2026011301"
|
||||
>
|
||||
</core-notiz>
|
||||
|
||||
|
||||
@@ -0,0 +1,359 @@
|
||||
import PvConfig from "../../../../index.ci.php/public/js/components/primevue/config/config.esm.min.js";
|
||||
import PvToast from "../../../../index.ci.php/public/js/components/primevue/toast/toast.esm.min.js";
|
||||
import PvConfirm from "../../../../index.ci.php/public/js/components/primevue/confirmdialog/confirmdialog.esm.min.js";
|
||||
import PvConfirmationService from "../../../../index.ci.php/public/js/components/primevue/confirmationservice/confirmationservice.esm.min.js";
|
||||
import {CoreRESTClient} from "../../RESTClient.js";
|
||||
|
||||
export default {
|
||||
init(app, $p) {
|
||||
let resolveReady;
|
||||
const readyPromise = new Promise(resolve => { resolveReady = resolve; });
|
||||
|
||||
const helperAppContainer = document.createElement('div');
|
||||
document.body.appendChild(helperAppContainer);
|
||||
|
||||
const helperApp = Vue.createApp({
|
||||
name: "FhcAlertApp",
|
||||
components: { PvToast, PvConfirm },
|
||||
methods: {
|
||||
mailToUrl(slotProps) {
|
||||
let mailTo = FHC_JS_DATA_STORAGE_OBJECT.systemerror_mailto;
|
||||
let subject = 'Meldung%20Systemfehler';
|
||||
let body = `
|
||||
Danke, dass Sie uns den Fehler melden. %0D%0A %0D%0A
|
||||
Bitte beschreiben Sie uns ausführlich das Problem.%0D%0A
|
||||
Bsp: Ich habe X ausgewählt und Y angelegt. Beim Speichern erhielt ich die Fehlermeldung. [Optional: Ich habe den Browser Z verwendet.]%0D%0A
|
||||
-----------------------------------------------------------------------------------------------------------------------------------%0D%0A
|
||||
PROBLEM: ... %0D%0A %0D%0A %0D%0A
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------------------------------%0D%0A
|
||||
Fehler URL: ` + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method + `%0D%0A
|
||||
Fehler Meldung: ` + slotProps.message.detail + `%0D%0A
|
||||
-----------------------------------------------------------------------------------------------------------------------------------%0D%0A %0D%0A
|
||||
Wir kümmern uns um eine rasche Behebung des Problems!`
|
||||
|
||||
return "mailto:" + mailTo + "?subject=" + subject + "&body=" + body;
|
||||
},
|
||||
openMessagecard(e) {
|
||||
bootstrap.Collapse.getOrCreateInstance(e.target.getAttribute('href')).toggle();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
showmaillink() { return FHC_JS_DATA_STORAGE_OBJECT.systemerror_mailto !== ''; }
|
||||
},
|
||||
template: /* html */`
|
||||
<pv-toast ref="toast" class="fhc-alert" :base-z-index="99999">
|
||||
<template #message="{ message }">
|
||||
<!--span :class="slotProps.iconClass"></span-->
|
||||
<div class="p-toast-message-text">
|
||||
<span class="p-toast-summary">{{ message.summary }}</span>
|
||||
<div v-if="message.detail && message.html" class="p-toast-detail" v-html="message.detail"></div>
|
||||
<div v-else-if="message.detail" class="p-toast-detail">{{ message.detail }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</pv-toast>
|
||||
<pv-toast ref="alert" class="fhc-alert" :base-z-index="99999" position="center">
|
||||
<template #message="slotProps">
|
||||
<i class="fa fa-circle-exclamation fa-2xl mt-3"></i>
|
||||
<div class="p-toast-message-text">
|
||||
<span class="p-toast-summary">{{slotProps.message.summary}}</span>
|
||||
<div class="p-toast-detail my-3">Sorry! Ein interner technischer Fehler ist aufgetreten.</div>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<a
|
||||
class="align-bottom flex-fill me-2"
|
||||
data-bs-toggle="collapse"
|
||||
:href="'#fhcAlertCollapseMessageCard' + slotProps.message.id"
|
||||
role="button"
|
||||
aria-expanded="false"
|
||||
:aria-controls="'fhcAlertCollapseMessageCard' + slotProps.message.id"
|
||||
@click="openMessagecard"
|
||||
>
|
||||
Fehler anzeigen
|
||||
</a>
|
||||
<a
|
||||
v-if="showmaillink"
|
||||
class="btn btn-primary flex-fill"
|
||||
target="_blank"
|
||||
:href="mailToUrl(slotProps)"
|
||||
>
|
||||
Fehler melden
|
||||
</a>
|
||||
</div>
|
||||
<div ref="messageCard" :id="'fhcAlertCollapseMessageCard' + slotProps.message.id" class="collapse mt-3">
|
||||
<div class="card card-body text-body small alertCollapseText">
|
||||
{{slotProps.message.detail}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</pv-toast>
|
||||
<pv-confirm group="fhcAlertConfirm"></pv-confirm>`
|
||||
});
|
||||
|
||||
// Link the helper app to the main app's phrasen system
|
||||
helperApp.config.globalProperties.$p = $p;
|
||||
helperApp.use(PvConfig);
|
||||
helperApp.use(PvConfirmationService);
|
||||
|
||||
const helperAppInstance = helperApp.mount(helperAppContainer);
|
||||
|
||||
const $fhcAlert = {
|
||||
// Internal storage for cross-plugin dependencies
|
||||
deps: { $p },
|
||||
ready: readyPromise,
|
||||
// Method used by FhcBase to inject the API later
|
||||
setDeps(deps) {
|
||||
Object.assign(this.deps, deps);
|
||||
// Alert is ready when both Phrases and API are present
|
||||
if (this.deps.$p && this.deps.$api) resolveReady();
|
||||
},
|
||||
|
||||
alertSuccess(message) {
|
||||
if (Array.isArray(message))
|
||||
return message.forEach(this.alertSuccess);
|
||||
helperAppInstance.$refs.toast.add({ severity: 'success', summary: 'Info', detail: message, life: 1000});
|
||||
},
|
||||
alertInfo(message) {
|
||||
if (Array.isArray(message))
|
||||
return message.forEach(this.alertInfo);
|
||||
helperAppInstance.$refs.toast.add({ severity: 'info', summary: 'Info', detail: message, life: 3000 });
|
||||
},
|
||||
alertWarning(message) {
|
||||
if (Array.isArray(message))
|
||||
return message.forEach(this.alertWarning);
|
||||
helperAppInstance.$refs.toast.add({ severity: 'warn', summary: 'Achtung', detail: message});
|
||||
},
|
||||
alertError(message) {
|
||||
if (Array.isArray(message))
|
||||
return message.forEach(this.alertError);
|
||||
helperAppInstance.$refs.toast.add({ severity: 'error', summary: 'Achtung', detail: message });
|
||||
},
|
||||
async alertSystemError(message) {
|
||||
//TODO(Manu) for translation of content of template: restructure in data
|
||||
//and update definitions with translations
|
||||
|
||||
await this.ready;
|
||||
|
||||
if (Array.isArray(message))
|
||||
return message.forEach(this.alertSystemError);
|
||||
helperAppInstance.$refs.alert.add({
|
||||
severity: 'error',
|
||||
summary: Vue.computed(() => this.deps.$p.t('alert/systemerror')),
|
||||
detail: message});
|
||||
},
|
||||
async confirmDelete() {
|
||||
await this.ready;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
helperAppInstance.$confirm.require({
|
||||
group: 'fhcAlertConfirm',
|
||||
header: Vue.computed(() => this.deps.$p.t('alert/attention')),
|
||||
message: Vue.computed(() => this.deps.$p.t('alert/confirm_delete')),
|
||||
acceptLabel: Vue.computed(() => this.deps.$p.t('ui/loeschen')),
|
||||
acceptClass: 'p-button-danger',
|
||||
rejectLabel: Vue.computed(() => this.deps.$p.t('ui/abbrechen')),
|
||||
rejectClass: 'p-button-secondary',
|
||||
accept() {
|
||||
resolve(true);
|
||||
},
|
||||
reject() {
|
||||
resolve(false);
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
confirm(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
helperAppInstance.$confirm.require({
|
||||
group: options?.group ?? 'fhcAlertConfirm',
|
||||
header: options?.header ?? Vue.computed(() => this.deps.$p.t('alert/attention')),
|
||||
message: options?.message ?? '',
|
||||
acceptLabel: options?.acceptLabel ?? 'Ok',
|
||||
acceptClass: options?.acceptClass ?? 'btn btn-primary',
|
||||
rejectLabel: options?.rejectLabel ?? Vue.computed(() => this.deps.$p.t('ui/abbrechen')),
|
||||
rejectClass: options?.rejectClass ?? 'btn btn-outline-secondary',
|
||||
accept() {
|
||||
resolve(true);
|
||||
},
|
||||
reject() {
|
||||
resolve(false);
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
alertDefault(severity, title, message, sticky = false, html = false) {
|
||||
let options = { severity: severity, summary: title, detail: message, html };
|
||||
|
||||
if (!sticky)
|
||||
options.life = 3000;
|
||||
|
||||
helperAppInstance.$refs.toast.add(options);
|
||||
},
|
||||
alertMultiple(messageArray, severity = 'info', title = 'Info', sticky = false, html = false){
|
||||
// Check, if array has only string values
|
||||
if (messageArray.every(message => typeof message === 'string')) {
|
||||
messageArray.forEach(message => this.alertDefault(severity, title, message, sticky, html));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
handleSystemError(error) {
|
||||
// don't show an error message to the user if the error was an aborted request
|
||||
if(error.hasOwnProperty('name') && error.name.toLowerCase() === "AbortError".toLowerCase())
|
||||
return;
|
||||
|
||||
// Error is string
|
||||
if (typeof error === 'string')
|
||||
return this.alertSystemError(error);
|
||||
|
||||
// Error is array of strings
|
||||
if (Array.isArray(error) && error.every(err => typeof err === 'string'))
|
||||
return error.every(this.alertSystemError);
|
||||
|
||||
// Error has been handled already
|
||||
if (error.hasOwnProperty('handled') && error.handled)
|
||||
return;
|
||||
|
||||
// Error is object
|
||||
if (typeof error === 'object' && error !== null) {
|
||||
let errMsg = '';
|
||||
|
||||
|
||||
if (error.hasOwnProperty('response') && error.response?.data?.retval)
|
||||
errMsg += 'Error Message: ' + (error.response.data.retval.message || error.response.data.retval) + '\r\n';
|
||||
else if (error.hasOwnProperty('message'))
|
||||
errMsg += 'Error Message: ' + error.message.toUpperCase() + '\r\n';
|
||||
|
||||
if (error.hasOwnProperty('config') && error.config.hasOwnProperty('url'))
|
||||
errMsg += 'Error ConfigURL: ' + error.config.url + '\r\n';
|
||||
|
||||
if (error.hasOwnProperty('stack'))
|
||||
errMsg += 'Error Stack: ' + error.stack + '\r\n';
|
||||
|
||||
// Fallback object error message
|
||||
if (errMsg == '')
|
||||
errMsg = 'Error Message: ' + JSON.stringify(error) + '\r\n';
|
||||
|
||||
errMsg += 'Error Controller Path: ' + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method;
|
||||
|
||||
return this.alertSystemError(errMsg);
|
||||
}
|
||||
|
||||
// Fallback
|
||||
this.alertSystemError('alertSystemError throws Generic Error\r\nError Controller Path: ' + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method);
|
||||
},
|
||||
handleSystemMessage(message) {
|
||||
// Message is string
|
||||
if (typeof message === 'string')
|
||||
return this.alertWarning(message);
|
||||
|
||||
// Message is array of strings
|
||||
if (Array.isArray(message)) {
|
||||
// If Array has only Strings
|
||||
if (message.every(msg => typeof msg === 'string'))
|
||||
return message.every(this.alertWarning);
|
||||
|
||||
// If Array has only Objects
|
||||
if (message.every(msg => typeof msg === 'object') && msg !== null) {
|
||||
return message.every(msg => {
|
||||
if (msg.hasOwnProperty('data') && msg.data.hasOwnProperty('retval')) {
|
||||
this.alertWarning(JSON.stringify(msg.data.retval));
|
||||
} else {
|
||||
this.alertSystemError(JSON.stringify(msg));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Message is Object with data property
|
||||
if (typeof message === 'object' && message !== null){
|
||||
if (message.hasOwnProperty('data') && message.data.hasOwnProperty('retval')) {
|
||||
// NOTE(chris): changed: alertSystemError => alertWarning
|
||||
this.alertWarning(JSON.stringify(message.data.retval));
|
||||
} else {
|
||||
this.alertSystemError(JSON.stringify(message));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback
|
||||
this.alertSystemError('alertSystemError throws Generic Error\r\nError Controller Path: ' + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method);
|
||||
},
|
||||
resetFormValidation(form) {
|
||||
const event = new Event('fhc-form-reset');
|
||||
form.querySelectorAll(['[data-fhc-form-validate],[data-fhc-form-error]']).forEach(el => el.dispatchEvent(event));
|
||||
/*const alert = form.querySelector('div.alert.alert-danger[role="alert"]');
|
||||
if (alert) {
|
||||
alert.innerHTML = '';
|
||||
alert.classList.add('d-none');
|
||||
}
|
||||
form.querySelectorAll('.invalid-feedback').forEach(n => n.remove());
|
||||
form.querySelectorAll('.is-invalid').forEach(n => n.classList.remove('is-invalid'));
|
||||
form.querySelectorAll('.is-valid').forEach(n => n.classList.remove('is-valid'));*/
|
||||
},
|
||||
handleFormValidation(error, form) {
|
||||
if (form === undefined) {
|
||||
if (error && error.nodeType === Node.ELEMENT_NODE)
|
||||
return err => this.handleFormValidation(err, error);
|
||||
} else {
|
||||
if (error?.response?.status == 400) {
|
||||
let errors = CoreRESTClient.getError(error.response.data);
|
||||
if (typeof errors !== "object")
|
||||
errors = error.response.data;
|
||||
|
||||
// NOTE(chris): reset form validation
|
||||
this.resetFormValidation(form);
|
||||
|
||||
// NOTE(chris): set form input validation
|
||||
const notFound = Object.entries(errors).filter(([key, detail]) => {
|
||||
const input = form.querySelector('[data-fhc-form-validate="' + key + '"]');
|
||||
if (!input)
|
||||
return true;
|
||||
|
||||
input.dispatchEvent(new CustomEvent('fhc-form-invalidate', {detail}));
|
||||
|
||||
/*const input = form.querySelector('[name="' + key + '"]');
|
||||
if (!input)
|
||||
return true;
|
||||
input.classList.add('is-invalid');
|
||||
const feedback = document.createElement('div');
|
||||
feedback.classList.add('invalid-feedback');
|
||||
feedback.innerHTML = detail;
|
||||
input.after(feedback);*/
|
||||
return false;
|
||||
}).map(arr => arr[1]);
|
||||
|
||||
|
||||
//const alert = form.querySelector('div.alert.alert-danger[role="alert"]');
|
||||
const alert = form.querySelector('[data-fhc-form-error]');
|
||||
if (alert && notFound.length) {
|
||||
alert.dispatchEvent(new CustomEvent('fhc-form-error', {detail: notFound}));
|
||||
/*notFound.forEach(txt => {
|
||||
const p = document.createElement('p');
|
||||
p.innerHTML = txt;
|
||||
alert.append(p);
|
||||
});
|
||||
|
||||
if (notFound.length) {
|
||||
alert.lastChild.classList.add('mb-0');
|
||||
alert.classList.remove('d-none');
|
||||
}*/
|
||||
} else {
|
||||
notFound.forEach(this.alertError);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (error?.response?.status == 400) {
|
||||
let errors = CoreRESTClient.getError(error.response.data);
|
||||
this.alertError((typeof errors === 'object') ? Object.values(errors) : errors);
|
||||
} else {
|
||||
this.handleSystemError(error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return $fhcAlert;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,591 @@
|
||||
/**
|
||||
* BaseApi.js - Contains the original api plugin methods call, get, post, etc.
|
||||
* Dependencies like phrasen($p) or alert($fhcAlert) are optional and can be injected at initialization
|
||||
* or at a later stage.
|
||||
*/
|
||||
export class BaseApi {
|
||||
constructor(deps = {}) {
|
||||
// optional dependencies like { $fhcAlert: ..., $p: ... }
|
||||
this.deps = deps;
|
||||
|
||||
this.resolveReady = null;
|
||||
this.ready = new Promise(resolve => { this.resolveReady = resolve; });
|
||||
|
||||
// If deps were passed in constructor, resolve immediately
|
||||
if (this.deps.$fhcAlert && this.deps.$p) this.resolveReady();
|
||||
|
||||
this.setupDefaultConfig()
|
||||
|
||||
this.axiosInstance = axios.create({
|
||||
timeout: 500000,
|
||||
baseURL: FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + "/"
|
||||
});
|
||||
|
||||
this.setupInterceptors();
|
||||
}
|
||||
|
||||
// === public functions START ===
|
||||
|
||||
// in case of api instantiation before vue app mount and later usage via fhcBase plugin
|
||||
setDependencies(deps) {
|
||||
Object.assign(this.deps, deps);
|
||||
if (this.deps.$fhcAlert && this.deps.$p) this.resolveReady();
|
||||
}
|
||||
|
||||
getUri(url) {
|
||||
return this.axiosInstance.getUri({ url });
|
||||
}
|
||||
|
||||
get(form, uri, params, config) {
|
||||
[uri, params, config] = this.get_config(form, uri, params, config);
|
||||
if (params) {
|
||||
config = config ? { ...config, params } : { params };
|
||||
}
|
||||
return this.axiosInstance.get(uri, config);
|
||||
}
|
||||
|
||||
post(form, uri, data, config) {
|
||||
[uri, data, config] = this.get_config(form, uri, data, config);
|
||||
return this.axiosInstance.post(uri, data, config);
|
||||
}
|
||||
|
||||
getErrorHandler(config) {
|
||||
return this.get_error_handler(config);
|
||||
}
|
||||
|
||||
async call(factory, configoverwrite, form) {
|
||||
if (Array.isArray(factory)) {
|
||||
return Promise.allSettled(factory.map((config, index) => {
|
||||
if (!Array.isArray(config)) config = ['#' + index, config];
|
||||
return this.call(config[1], { errorHeader: config[0], errorHandling: false });
|
||||
})).then(result => {
|
||||
const [ , , config ] = this.get_config(form, undefined, undefined, configoverwrite || {});
|
||||
const errorConfig = this.get_error_handler(config);
|
||||
|
||||
if (!errorConfig.success && !errorConfig.fail) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const typedErrors = {};
|
||||
for (let res of result) {
|
||||
const [ allowed, item ] = res.status === 'fulfilled'
|
||||
? [ errorConfig.success, res.value ]
|
||||
: [ errorConfig.fail, res.reason ];
|
||||
if (!allowed)
|
||||
return;
|
||||
|
||||
const errors = this.popHandleableErrors(errorConfig, this.get_error_list(item));
|
||||
|
||||
for (let type in errors) {
|
||||
if (!typedErrors[type])
|
||||
typedErrors[type] = {
|
||||
[item.config.errorHeader]: errors[type]
|
||||
};
|
||||
else
|
||||
typedErrors[type][item.config.errorHeader] = errors[type];
|
||||
}
|
||||
};
|
||||
|
||||
for (let errType in typedErrors) {
|
||||
errorConfig.handler[errType](typedErrors[errType]);
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
let { method = 'get', url, params, config } = factory;
|
||||
if (configoverwrite !== undefined) config = configoverwrite;
|
||||
method = method.toLowerCase();
|
||||
|
||||
return method === 'post' ? this.post(form, url, params, config) : this.get(form, url, params, config);
|
||||
}
|
||||
|
||||
// === public functions END ===
|
||||
|
||||
// === private functions START ===
|
||||
|
||||
setupInterceptors() {
|
||||
|
||||
this.axiosInstance.interceptors.request.use(config => {
|
||||
if (config.method != 'post' || !config.data)
|
||||
return config;
|
||||
|
||||
if (config.data instanceof FormData)
|
||||
return config;
|
||||
|
||||
if (!Object.values(config.data).every(item => {
|
||||
if (item instanceof FileList)
|
||||
return false;
|
||||
if (Array.isArray(item))
|
||||
return item.every(i => !(i instanceof File));
|
||||
return true;
|
||||
})) {
|
||||
const newData = Object.entries(config.data).reduce((nd, [key, item]) => {
|
||||
if (item instanceof FileList) {
|
||||
for (const file of item)
|
||||
nd.FormData.append(key + (item.length > 1 ? '[]' : ''), file);
|
||||
} else if (Array.isArray(item)) {
|
||||
if (item.every(i => !(i instanceof File))) {
|
||||
nd.jsondata[key] = item;
|
||||
} else {
|
||||
item.forEach(file => nd.FormData.append(key + (item.length > 1 ? '[]' : ''), file));
|
||||
}
|
||||
} else {
|
||||
nd.jsondata[key] = item;
|
||||
}
|
||||
return nd;
|
||||
}, {
|
||||
FormData: new FormData(),
|
||||
jsondata: {}
|
||||
});
|
||||
newData.FormData.append('_jsondata', JSON.stringify(newData.jsondata));
|
||||
config.data = newData.FormData;
|
||||
}
|
||||
|
||||
return config;
|
||||
});
|
||||
|
||||
this.axiosInstance.interceptors.response.use(
|
||||
response => {
|
||||
if (response.config?.errorHandling == 'off'
|
||||
|| response.config?.errorHandling === false
|
||||
|| response.config?.errorHandling == 'fail')
|
||||
return this.clean_return_value(response);
|
||||
|
||||
// NOTE(chris): loop through errors
|
||||
if (response.data.errors)
|
||||
response.data.errors = response.data.errors.filter(
|
||||
err => (response.config[err.type + 'ErrorHandler'] || this.DEFAULT_ERROR_CONFIG.handler[err.type])(err, response.config)
|
||||
);
|
||||
|
||||
return this.clean_return_value(response);
|
||||
},
|
||||
error => {
|
||||
if (error.code == 'ERR_CANCELED')
|
||||
return Promise.reject({ handled: true, ...error });
|
||||
|
||||
const errorConfig = this.get_error_handler(error.config);
|
||||
|
||||
if (!errorConfig.fail)
|
||||
return Promise.reject(error);
|
||||
|
||||
const remaining = this.get_error_list(error);
|
||||
|
||||
const errors = this.popHandleableErrors(errorConfig, remaining);
|
||||
|
||||
for (let type in errors) {
|
||||
errorConfig.handler[type](errors[type]);
|
||||
}
|
||||
|
||||
if (remaining.length)
|
||||
return Promise.reject(error);
|
||||
|
||||
return Promise.reject({ handled: true, ...error });
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
setupDefaultConfig() {
|
||||
|
||||
this.DEFAULT_ERROR_CONFIG = {
|
||||
success: true,
|
||||
fail: true,
|
||||
combine: {
|
||||
form: ['validation', 'general'],
|
||||
toast: ['validation', 'general', 'not_found', 'site_failed']
|
||||
},
|
||||
handler: {
|
||||
form: (form, errors) => {
|
||||
form.clearValidation();
|
||||
errors.forEach(err => form.setFeedback(
|
||||
false,
|
||||
err.messages || err.message
|
||||
));
|
||||
},
|
||||
toast: async (errors) => {
|
||||
await this.ready;
|
||||
|
||||
async function _format_toast(errors) {
|
||||
errors = errors.reduce((result, err) => {
|
||||
switch (err.type) {
|
||||
case 'not_found':
|
||||
case 'site_failed':
|
||||
if (err.message)
|
||||
result[err.message] = [err.url];
|
||||
else
|
||||
result._default = [err.url];
|
||||
break;
|
||||
case 'general':
|
||||
if (!result._default)
|
||||
result._default = [];
|
||||
result._default.push(err.message);
|
||||
break;
|
||||
case 'validation':
|
||||
Object.entries(err.messages)
|
||||
.forEach(([field, msg]) => {
|
||||
if (!result[field])
|
||||
result[field] = [];
|
||||
if (Array.isArray(msg))
|
||||
result[field].push(...msg);
|
||||
else
|
||||
result[field].push(msg);
|
||||
});
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}, {});
|
||||
let counter = 0;
|
||||
const msgs = await Promise.all(Object.entries(errors)
|
||||
.sort((a, b) => ['_default'].indexOf(b[0]) - ['_default'].indexOf(a[0])) // sort _default first
|
||||
.map(async ([field, msgs]) => {
|
||||
if (field == '_default') {
|
||||
await this.deps.$p.loadCategory('dashboard');
|
||||
const general = this.deps.$p.t('dashboard/general');
|
||||
field = '<dt class="d-none">' + general + '</dt>';
|
||||
} else {
|
||||
field = '<dt>' + field + '</dt>';
|
||||
}
|
||||
counter += msgs.length;
|
||||
return field
|
||||
+ '<dd>'
|
||||
+ msgs.join('</dd><dd>')
|
||||
+ '</dd>';
|
||||
}));
|
||||
return {
|
||||
counter,
|
||||
msgs
|
||||
}
|
||||
}
|
||||
|
||||
let counter, msgs;
|
||||
if (Array.isArray(errors)) {
|
||||
({ counter, msgs } = await _format_toast(errors));
|
||||
} else {
|
||||
({ counter, msgs } = await Object.entries(errors)
|
||||
.reduce(async (res, [title, errs]) => {
|
||||
const result = await res;
|
||||
const { counter, msgs } = await _format_toast(errs);
|
||||
result.counter += counter;
|
||||
result.msgs.push('<dt>'
|
||||
+ title
|
||||
+ '</dt><dd><dl>'
|
||||
+ msgs.join('')
|
||||
+ '</dl></dd>');
|
||||
return result;
|
||||
}, Promise.resolve({ counter: 0, msgs: []})));
|
||||
}
|
||||
|
||||
await this.deps.$p.loadCategory('ui');
|
||||
const n_errors = this.deps.$p.t('ui/n_errors', { n: counter });
|
||||
|
||||
this.deps.$fhcAlert.alertDefault(
|
||||
'error',
|
||||
n_errors,
|
||||
'<dl>' + msgs.join('') + '</dl>',
|
||||
true,
|
||||
true
|
||||
);
|
||||
},
|
||||
php: async (errors) => {
|
||||
await this.ready;
|
||||
|
||||
this._send_array_or_object(errors, (error, title) => {
|
||||
var message = '';
|
||||
message += 'Message: ' + error.message + '\n\n';
|
||||
message += 'Filename: ' + error.filename + '\n';
|
||||
message += 'Line Number: ' + error.line + '\n';
|
||||
if (error.backtrace && error.backtrace.length) {
|
||||
message += '\nBacktrace: ';
|
||||
error.backtrace.forEach(err => {
|
||||
message += '\n\tFile: ' + err.file + '\n';
|
||||
message += '\tLine: ' + err.line + '\n';
|
||||
message += '\tFunction: ' + err.function + '\n';
|
||||
});
|
||||
}
|
||||
switch (error.severity) {
|
||||
case 'Warning':
|
||||
case 'Core Warning':
|
||||
case 'Compile Warning':
|
||||
case 'User Warning':
|
||||
if (title)
|
||||
title += ': PHP ' + error.severity;
|
||||
else
|
||||
title = 'PHP ' + error.severity;
|
||||
this.deps.$fhcAlert.alertDefault('warn', title, message, true);
|
||||
break;
|
||||
case 'Notice':
|
||||
case 'User Notice':
|
||||
case 'Runtime Notice':
|
||||
if (title)
|
||||
title += ': PHP ' + error.severity;
|
||||
else
|
||||
title = 'PHP ' + error.severity;
|
||||
this.deps.$fhcAlert.alertDefault('info', title, message, true);
|
||||
break;
|
||||
default:
|
||||
message = 'Type: PHP ' + error.severity + '\n\n' + message;
|
||||
if (title)
|
||||
message = title + '\n\n' + message;
|
||||
this.deps.$fhcAlert.alertSystemError(message);
|
||||
break;
|
||||
}
|
||||
});
|
||||
},
|
||||
exception: async (errors) => {
|
||||
await this.ready;
|
||||
|
||||
this._send_array_or_object(errors, (error, title) => {
|
||||
var message = '';
|
||||
if (title)
|
||||
message += title + '\n\n';
|
||||
message += 'Type: ' + error.class + '\n\n';
|
||||
message += 'Message: ' + error.message + '\n\n';
|
||||
message += 'Filename: ' + error.filename + '\n';
|
||||
message += 'Line Number: ' + error.line + '\n';
|
||||
if (error.backtrace && error.backtrace.length) {
|
||||
message += '\nBacktrace: ';
|
||||
error.backtrace.forEach(err => {
|
||||
message += '\n\tFile: ' + err.file + '\n';
|
||||
message += '\tLine: ' + err.line + '\n';
|
||||
message += '\tFunction: ' + err.function + '\n';
|
||||
});
|
||||
}
|
||||
this.deps.$fhcAlert.alertSystemError(message);
|
||||
});
|
||||
},
|
||||
db: async (errors) => {
|
||||
await this.ready;
|
||||
|
||||
this._send_array_or_object(errors, (error, title) => {
|
||||
var message = '';
|
||||
if (title)
|
||||
message += title + '\n\n';
|
||||
if (error.heading !== undefined)
|
||||
message += error.heading + '\n\n';
|
||||
if (error.code !== undefined)
|
||||
message += 'Code: ' + error.code + '\n\n';
|
||||
if (error.sql !== undefined)
|
||||
message += 'SQL: ' + error.sql + '\n\n';
|
||||
if (error.message !== undefined)
|
||||
message += 'Message: ' + error.message + '\n\n';
|
||||
else if (error.messages !== undefined)
|
||||
message += 'Messages: ' + error.messages.join('\n\t') + '\n\n';
|
||||
if (error.filename !== undefined)
|
||||
message += 'Filename: ' + error.filename + '\n';
|
||||
if (error.line !== undefined)
|
||||
message += 'Line Number: ' + error.line + '\n';
|
||||
|
||||
this.deps.$fhcAlert.alertSystemError(message);
|
||||
});
|
||||
},
|
||||
auth: async (errors) => {
|
||||
await this.ready;
|
||||
|
||||
this._send_array_or_object(errors, (error, title) => {
|
||||
if (title)
|
||||
title += ': ' + error.message;
|
||||
else
|
||||
title = error.message;
|
||||
|
||||
var message = '';
|
||||
message += 'Controller name: ' + error.controller + '\n';
|
||||
message += 'Method name: ' + error.method + '\n';
|
||||
message += 'Required permissions: ' + error.required_permissions;
|
||||
|
||||
this.deps.$fhcAlert.alertDefault(
|
||||
'error',
|
||||
title,
|
||||
message,
|
||||
true
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
_send_array_or_object(errors, func) {
|
||||
if (!errors) return;
|
||||
|
||||
if (Array.isArray(errors)) {
|
||||
errors.forEach(error => func(error));
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle Single Error Object
|
||||
if (errors.type) {
|
||||
func(errors);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle Category Container
|
||||
Object.entries(errors).forEach(([title, value]) => {
|
||||
const errorList = Array.isArray(value) ? value : [value];
|
||||
|
||||
errorList.forEach(error => {
|
||||
if (error && typeof error === 'object') {
|
||||
func(error, title);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
get_config(form, uri, data, config) {
|
||||
if (typeof form == 'string' && config === undefined) {
|
||||
[uri, data, config] = [form, uri, data];
|
||||
form = undefined;
|
||||
} else if (form) {
|
||||
if (typeof form != 'object')
|
||||
throw new TypeError('Parameter 1 of _get_config must be an object or a string');
|
||||
if (uri === undefined && data === undefined && config === undefined) {
|
||||
config = form;
|
||||
form = undefined;
|
||||
}
|
||||
}
|
||||
if (form) {
|
||||
// NOTE(chris): check if form is fhc-form
|
||||
if (!form.clearValidation || !form.setFeedback)
|
||||
throw new TypeError("'form' is not a Form Component");
|
||||
|
||||
form = {
|
||||
clearValidation: form.clearValidation,
|
||||
setFeedback: form.setFeedback
|
||||
};
|
||||
|
||||
if (config)
|
||||
config.form = form;
|
||||
else
|
||||
config = {form};
|
||||
}
|
||||
|
||||
return [uri, data, config];
|
||||
}
|
||||
|
||||
clean_return_value(response) {
|
||||
if (typeof response.data === 'string' || response.data instanceof String)
|
||||
return this.clean_return_value({ data: response });
|
||||
|
||||
const result = response.data;
|
||||
delete response.data;
|
||||
if (!result)
|
||||
return {meta: {response}, data: null};
|
||||
if (!result.meta)
|
||||
result.meta = { response };
|
||||
else
|
||||
result.meta.response = response;
|
||||
return result;
|
||||
}
|
||||
|
||||
merge_error_config(config) {
|
||||
if (config === false || config === 'off')
|
||||
return { ...this.DEFAULT_ERROR_CONFIG, success: false, fail: false };
|
||||
|
||||
if (!config || config === true)
|
||||
return { ...this.DEFAULT_ERROR_CONFIG };
|
||||
|
||||
if (config === 'success')
|
||||
return { ...this.DEFAULT_ERROR_CONFIG, fail: false };
|
||||
|
||||
if (config === 'fail')
|
||||
return { ...this.DEFAULT_ERROR_CONFIG, success: false };
|
||||
|
||||
const { success, fail, handler, combine } = config;
|
||||
|
||||
config = { ...this.DEFAULT_ERROR_CONFIG };
|
||||
|
||||
Object.entries({ fail, success }).forEach(([key, value]) => {
|
||||
if (value !== undefined)
|
||||
config[key] = value;
|
||||
});
|
||||
Object.entries({ handler, combine }).forEach(([key, value]) => {
|
||||
if (value !== undefined)
|
||||
config[key] = { ...config[key], ...value };
|
||||
});
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
get_error_handler(config) {
|
||||
const result = this.merge_error_config(config?.errorHandling);
|
||||
|
||||
if (!config?.form) {
|
||||
result.combine = { ...result.combine, form: [] };
|
||||
} else {
|
||||
const formHandler = result.handler.form;
|
||||
result.handler = { ...result.handler, form: errors => formHandler(config.form, errors) };
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
get_error_list(error) {
|
||||
if (error.response) {
|
||||
if (error.response.status == 404) {
|
||||
return [{
|
||||
type: 'not_found',
|
||||
message: error.message,
|
||||
url: error.request.responseURL
|
||||
}];
|
||||
} else {
|
||||
if (error.response.data.errors == undefined) return [];
|
||||
return error.response.data.errors;
|
||||
}
|
||||
} else if (error.request) {
|
||||
return [{
|
||||
type: 'site_failed',
|
||||
message: error.message,
|
||||
url: error.request.responseURL
|
||||
}];
|
||||
} else {
|
||||
return [{
|
||||
type: 'script',
|
||||
message: error.message
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
popHandleableErrors(errorHandling, errors) {
|
||||
const result = {};
|
||||
const copy = [];
|
||||
|
||||
if (errors == undefined) return {};
|
||||
|
||||
while (errors.length)
|
||||
copy.push(errors.pop());
|
||||
for (let error of copy) {
|
||||
let type = error.type;
|
||||
let newType = null;
|
||||
for (let t in errorHandling.combine) {
|
||||
let newTypeCombinesType = errorHandling
|
||||
.combine[t]
|
||||
.includes(type);
|
||||
let newTypeHasHandler = errorHandling.handler[t];
|
||||
if (newTypeCombinesType && newTypeHasHandler) {
|
||||
newType = t;
|
||||
if (newType == 'form')
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newType)
|
||||
type = newType;
|
||||
const handler = errorHandling.handler[type];
|
||||
if (handler) {
|
||||
if (!result[type])
|
||||
result[type] = [];
|
||||
if (Array.isArray(error))
|
||||
result[type].push(...error);
|
||||
else
|
||||
result[type].push(error);
|
||||
continue;
|
||||
}
|
||||
errors.push(error);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// === private functions END ===
|
||||
|
||||
}
|
||||
|
||||
export default BaseApi;
|
||||
@@ -0,0 +1,100 @@
|
||||
import ApiPhrasen from '../../api/factory/phrasen.js';
|
||||
|
||||
const categories = Vue.reactive({});
|
||||
const loadingModules = {};
|
||||
let user_language = Vue.ref(FHC_JS_DATA_STORAGE_OBJECT.user_language);
|
||||
|
||||
export const user_locale = Vue.computed(() => {
|
||||
if (!user_language.value) return null;
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.server_languages.find(l => l.sprache == user_language.value).LC_Time;
|
||||
});
|
||||
|
||||
function extractCategory(obj, category) {
|
||||
return obj.filter(e => e.category == category).reduce((res, elem) => {
|
||||
if (!res[elem.phrase]) res[elem.phrase] = elem.text;
|
||||
return res;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function getValueForLoadedPhrase(category, phrase, params) {
|
||||
let result = categories[category][phrase];
|
||||
if (!result)
|
||||
return '<< PHRASE ' + phrase + '>>';
|
||||
if (params)
|
||||
result = result.replace(/\{([^}]*)\}/g, (match, p1) => params[p1] === undefined ? match : params[p1]);
|
||||
return result;
|
||||
}
|
||||
|
||||
export default {
|
||||
init(app) {
|
||||
// Create a controller to resolve the promise later
|
||||
let resolveReady;
|
||||
const readyPromise = new Promise(resolve => { resolveReady = resolve; });
|
||||
|
||||
const $p = {
|
||||
deps: {},
|
||||
ready: readyPromise,
|
||||
setDeps(deps) {
|
||||
Object.assign(this.deps, deps);
|
||||
// Once we have the API, we are ready to load data
|
||||
if (this.deps.$api) resolveReady();
|
||||
},
|
||||
user_language,
|
||||
user_locale,
|
||||
|
||||
async loadCategory(category) {
|
||||
if (Array.isArray(category))
|
||||
return Promise.all(category.map(cat => this.loadCategory(cat)));
|
||||
|
||||
// 2. SAFETY: Check if API is available via deps
|
||||
await this.ready;
|
||||
|
||||
if (!loadingModules[category])
|
||||
loadingModules[category] = this.deps.$api
|
||||
.call(ApiPhrasen.loadCategory(category))
|
||||
.then(res => res?.data ? extractCategory(res.data, category) : {})
|
||||
.then(res => {
|
||||
categories[category] = res;
|
||||
});
|
||||
return loadingModules[category];
|
||||
},
|
||||
t_ref(category, phrase, params) {
|
||||
console.warn('deprecated');
|
||||
return Vue.computed(() => this.t(category, phrase, params));
|
||||
},
|
||||
|
||||
t(category, phrase, params) {
|
||||
if (params === undefined && (
|
||||
(Array.isArray(category) && category.length == 2) ||
|
||||
(category.split && category.split('/').length == 2))
|
||||
) {
|
||||
params = phrase;
|
||||
[category, phrase] = category.split ? category.split('/') : category;
|
||||
}
|
||||
if (phrase === undefined) {
|
||||
console.error('invalid input', category, phrase, params);
|
||||
return '';
|
||||
}
|
||||
let val = Vue.computed(() => {
|
||||
if (!categories[category])
|
||||
return '';
|
||||
return getValueForLoadedPhrase(category, phrase, params);
|
||||
});
|
||||
if (!categories[category])
|
||||
this.loadCategory(category);
|
||||
return val.value;
|
||||
},
|
||||
|
||||
async setLanguage(language) {
|
||||
await this.ready;
|
||||
const catArray = Object.keys(categories);
|
||||
return this.deps.$api.call(ApiPhrasen.setLanguage(catArray, language)).then(res => {
|
||||
res.data.forEach(row => { categories[row.category][row.phrase] = row.text; });
|
||||
user_language.value = language;
|
||||
return res;
|
||||
});
|
||||
}
|
||||
};
|
||||
return $p;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,37 @@
|
||||
import Phrasen from './BasePhrasen.js';
|
||||
import Alert from './BaseAlert.js';
|
||||
import { BaseApi } from './BaseApi.js';
|
||||
|
||||
export default {
|
||||
|
||||
install(app, options = {}) {
|
||||
// init in order
|
||||
const $p = Phrasen.init(app);
|
||||
const $fhcAlert = Alert.init(app, $p);
|
||||
|
||||
// try to reuse existing CoreRESTClient api instance if one has been active since before
|
||||
// fhcBase Plugin install
|
||||
let $api = app.config.globalProperties.$api;
|
||||
if (!($api instanceof BaseApi)) {
|
||||
$api = new BaseApi({ $fhcAlert, $p }, options);
|
||||
} else {
|
||||
// If api existed pre-app install
|
||||
$api.setDependencies({ $fhcAlert, $p });
|
||||
}
|
||||
|
||||
// set ready promise for awaiting async functions
|
||||
$p.setDeps({ $api, $fhcAlert });
|
||||
$fhcAlert.setDeps({ $api });
|
||||
|
||||
// globalProperties Binding & provide
|
||||
app.config.globalProperties.$p = $p;
|
||||
app.config.globalProperties.$fhcAlert = $fhcAlert;
|
||||
app.config.globalProperties.$api = $api;
|
||||
app.config.globalProperties.$fhcApi = $api;
|
||||
app.provide('$api', $api);
|
||||
app.provide('$fhcApi', $api);
|
||||
app.provide('$p', $p);
|
||||
app.provide('$fhcAlert', $fhcAlert);
|
||||
}
|
||||
|
||||
};
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
@@ -84,9 +84,11 @@ require_once('dbupdate_3.4/60882_lehrfaecherverteilung_favorites.php');
|
||||
require_once('dbupdate_3.4/66982_berufsschule.php');
|
||||
require_once('dbupdate_3.4/40314_electronic_onboarding_anbindung_ida.php');
|
||||
require_once('dbupdate_3.4/47972_pruefungsverwaltung_ects_angabe.php');
|
||||
require_once('dbupdate_3.4/62063_lv_evaluierung.php');
|
||||
require_once('dbupdate_3.4/67490_studstatus_suche_abort_controller_haengt.php');
|
||||
require_once('dbupdate_3.4/69065_Projektarbeiten_Firmen_verwalten.php');
|
||||
require_once('dbupdate_3.4/68744_StV_settings.php');
|
||||
require_once('dbupdate_3.4/62889_reihungstest_ueberwachung_mit_constructor.php');
|
||||
|
||||
// *** Pruefung und hinzufuegen der neuen Attribute und Tabellen
|
||||
echo '<H2>Pruefe Tabellen und Attribute!</H2>';
|
||||
@@ -254,7 +256,7 @@ $tabellen=array(
|
||||
"lehre.tbl_lehrmittel" => array("lehrmittel_kurzbz","beschreibung","ort_kurzbz"),
|
||||
"lehre.tbl_lehrmodus" => array("lehrmodus_kurzbz","bezeichnung_mehrsprachig","aktiv"),
|
||||
"lehre.tbl_lehrtyp" => array("lehrtyp_kurzbz","bezeichnung"),
|
||||
"lehre.tbl_lehrveranstaltung" => array("lehrveranstaltung_id","kurzbz","bezeichnung","lehrform_kurzbz","studiengang_kz","semester","sprache","ects","semesterstunden","anmerkung","lehre","lehreverzeichnis","aktiv","planfaktor","planlektoren","planpersonalkosten","plankostenprolektor","koordinator","sort","zeugnis","projektarbeit","updateamum","updatevon","insertamum","insertvon","ext_id","bezeichnung_english","orgform_kurzbz","incoming","lehrtyp_kurzbz","oe_kurzbz","raumtyp_kurzbz","anzahlsemester","semesterwochen","lvnr","farbe","semester_alternativ","old_lehrfach_id","sws","lvs","alvs","lvps","las","benotung","lvinfo","lehrauftrag","lehrmodus_kurzbz","lehrveranstaltung_template_id"),
|
||||
"lehre.tbl_lehrveranstaltung" => array("lehrveranstaltung_id","kurzbz","bezeichnung","lehrform_kurzbz","studiengang_kz","semester","sprache","ects","semesterstunden","anmerkung","lehre","lehreverzeichnis","aktiv","planfaktor","planlektoren","planpersonalkosten","plankostenprolektor","koordinator","sort","zeugnis","projektarbeit","updateamum","updatevon","insertamum","insertvon","ext_id","bezeichnung_english","orgform_kurzbz","incoming","lehrtyp_kurzbz","oe_kurzbz","raumtyp_kurzbz","anzahlsemester","semesterwochen","lvnr","farbe","semester_alternativ","old_lehrfach_id","sws","lvs","alvs","lvps","las","benotung","lvinfo","lehrauftrag","lehrmodus_kurzbz","lehrveranstaltung_template_id", "evaluierung"),
|
||||
"lehre.tbl_lehrveranstaltung_kompatibel" => array("lehrveranstaltung_id","lehrveranstaltung_id_kompatibel"),
|
||||
"lehre.tbl_lvangebot" => array("lvangebot_id","lehrveranstaltung_id","studiensemester_kurzbz","gruppe_kurzbz","incomingplaetze","gesamtplaetze","anmeldefenster_start","anmeldefenster_ende","insertamum","insertvon","updateamum","updatevon"),
|
||||
"lehre.tbl_lvregel" => array("lvregel_id","lvregeltyp_kurzbz","operator","parameter","lvregel_id_parent","lehrveranstaltung_id","studienplan_lehrveranstaltung_id","insertamum","insertvon","updateamum","updatevon"),
|
||||
@@ -359,7 +361,7 @@ $tabellen=array(
|
||||
"public.tbl_profil_update_status" => array("status_kurzbz","beschreibung","bezeichnung_mehrsprachig"),
|
||||
"public.tbl_profil_update_topic" => array("topic_kurzbz","beschreibung","bezeichnung_mehrsprachig"),
|
||||
"public.tbl_raumtyp" => array("raumtyp_kurzbz","beschreibung","kosten","aktiv"),
|
||||
"public.tbl_reihungstest" => array("reihungstest_id","studiengang_kz","ort_kurzbz","anmerkung","datum","uhrzeit","updateamum","updatevon","insertamum","insertvon","ext_id","freigeschaltet","max_teilnehmer","oeffentlich","studiensemester_kurzbz","aufnahmegruppe_kurzbz","stufe","anmeldefrist","zugangs_ueberpruefung","zugangscode"),
|
||||
"public.tbl_reihungstest" => array("reihungstest_id","studiengang_kz","ort_kurzbz","anmerkung","datum","uhrzeit","updateamum","updatevon","insertamum","insertvon","ext_id","freigeschaltet","max_teilnehmer","oeffentlich","studiensemester_kurzbz","aufnahmegruppe_kurzbz","stufe","anmeldefrist","zugangs_ueberpruefung","zugangscode", "externe_ueberwachung"),
|
||||
"public.tbl_rueckstellung" => array("rueckstellung_id","person_id","status_kurzbz","datum_bis","insertamum","insertvon"),
|
||||
"public.tbl_rueckstellung_status" => array("status_kurzbz", "bezeichnung_mehrsprachig", "sort", "aktiv"),
|
||||
"public.tbl_rt_ort" => array("rt_id","ort_kurzbz","uid"),
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
if (! defined('DB_NAME')) exit('No direct script access allowed');
|
||||
|
||||
//Add column evaluierung to lehre.tbl_lehrveranstaltung
|
||||
if(!@$db->db_query("SELECT evaluierung FROM lehre.tbl_lehrveranstaltung LIMIT 1"))
|
||||
{
|
||||
$qry = "ALTER TABLE lehre.tbl_lehrveranstaltung ADD COLUMN evaluierung boolean NOT NULL DEFAULT true;
|
||||
COMMENT ON COLUMN lehre.tbl_lehrveranstaltung.evaluierung IS 'TRUE wenn für diese LV eine LV-Evaluierung durchgeführt wird';
|
||||
";
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_lehrveranstaltung '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>Spalte evaluierung zu Tabelle lehre.tbl_lehrveranstaltung hinzugefügt';
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
if (! defined('DB_NAME')) exit('No direct script access allowed');
|
||||
|
||||
if(!$result = @$db->db_query("SELECT externe_ueberwachung FROM public.tbl_reihungstest LIMIT 1"))
|
||||
{
|
||||
$qry = "ALTER TABLE public.tbl_reihungstest ADD COLUMN externe_ueberwachung boolean NOT NULL DEFAULT false;";
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>public.tbl_reihungstest: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>public.tbl_reihungstest: Spalte externe_ueberwachung hinzugefuegt';
|
||||
}
|
||||
|
||||
if(!$result = @$db->db_query("SELECT 1 FROM testtool.tbl_externe_ueberwachung LIMIT 1"))
|
||||
{
|
||||
$qry = "CREATE TABLE testtool.tbl_externe_ueberwachung (
|
||||
externe_ueberwachung_id INTEGER NOT NULL,
|
||||
prestudent_id INTEGER NOT NULL,
|
||||
session_id UUID NOT NULL,
|
||||
insertamum TIMESTAMP DEFAULT NOW(),
|
||||
CONSTRAINT tbl_externe_ueberwachung_pk PRIMARY KEY(externe_ueberwachung_id)
|
||||
);
|
||||
CREATE SEQUENCE testtool.tbl_externe_ueberwachungg_id_seq
|
||||
INCREMENT BY 1
|
||||
NO MAXVALUE
|
||||
NO MINVALUE
|
||||
CACHE 1;
|
||||
ALTER TABLE testtool.tbl_externe_ueberwachung ALTER COLUMN externe_ueberwachung_id SET DEFAULT nextval('testtool.tbl_externe_ueberwachungg_id_seq');
|
||||
ALTER TABLE testtool.tbl_externe_ueberwachung ADD CONSTRAINT fk_prestudent_externe_ueberwachung FOREIGN KEY (prestudent_id) REFERENCES public.tbl_prestudent (prestudent_id) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE testtool.tbl_externe_ueberwachung ADD CONSTRAINT unique_externe_ueberwachung_session_id UNIQUE (session_id);
|
||||
GRANT SELECT, INSERT ON testtool.tbl_externe_ueberwachung TO vilesci;
|
||||
GRANT SELECT, INSERT ON testtool.tbl_externe_ueberwachung TO web;
|
||||
GRANT SELECT, UPDATE ON testtool.tbl_externe_ueberwachungg_id_seq TO vilesci;
|
||||
GRANT SELECT, UPDATE ON testtool.tbl_externe_ueberwachungg_id_seq TO web;";
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>testtool.tbl_externe_ueberwachung: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>testtool.tbl_externe_ueberwachung: table created';
|
||||
}
|
||||
+551
-465
File diff suppressed because it is too large
Load Diff
@@ -122,6 +122,7 @@
|
||||
$lv->benotung = isset($_POST['benotung']);
|
||||
$lv->lvinfo = isset($_POST['lvinfo']);
|
||||
$lv->lehrauftrag = isset($_POST['lehrauftrag']);
|
||||
$lv->evaluierung = isset($_POST['evaluierung']);
|
||||
$lv->lehrveranstaltung_template_id = $lv->lehrtyp_kurzbz == 'tpl' ? '' : $_POST['lehrveranstaltung_template_id'];
|
||||
|
||||
if(!$lv->save())
|
||||
@@ -446,6 +447,10 @@
|
||||
<td>Lehrauftrag</td>
|
||||
<td><input type="checkbox" name="lehrauftrag" '.($lv->lehrauftrag?'checked':'').'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Evaulierung</td>
|
||||
<td><input type="checkbox" name="evaluierung" '.($lv->evaluierung?'checked':'').'></td>
|
||||
</tr>
|
||||
<tr id="lehrveranstaltung_template_id">
|
||||
<td>Template</td>
|
||||
<td colspan="2"><input type="text" name="lehrveranstaltung_template_id" value="'.$lv->lehrveranstaltung_template_id.'" size="6"> <span class="text-template_name"></span></td>
|
||||
|
||||
@@ -1458,6 +1458,7 @@ if(isset($_POST['speichern']) || isset($_POST['kopieren']))
|
||||
$reihungstest->anmeldefrist = $datum_obj->formatDatum($_POST['anmeldefrist']);
|
||||
$reihungstest->zugangs_ueberpruefung = false;
|
||||
$reihungstest->zugangscode = null;
|
||||
$reihungstest->externe_ueberwachung = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1474,6 +1475,7 @@ if(isset($_POST['speichern']) || isset($_POST['kopieren']))
|
||||
$reihungstest->updatevon = $user;
|
||||
$reihungstest->zugangs_ueberpruefung = isset($_POST['zugangs_ueberpruefung']);
|
||||
$reihungstest->zugangscode = ($_POST['zugangcode'] === '' ? null : $_POST['zugangcode']);
|
||||
$reihungstest->externe_ueberwachung = isset($_POST['externe_ueberwachung']);
|
||||
}
|
||||
$reihungstest->studiengang_kz = $_POST['studiengang_kz'];
|
||||
//$reihungstest->ort_kurzbz = $_POST['ort_kurzbz'];
|
||||
@@ -2571,6 +2573,14 @@ $studienplaene_list = implode(',', array_keys($studienplaene_arr));
|
||||
<input type="number" class="input" id="zugangcode" name="zugangcode" value="<?php echo $db->convert_html_chars($reihungstest->zugangscode) ?>"> (Verpflichtend, wenn die Zugangsüberprüfung aktiviert ist)
|
||||
</td>
|
||||
</tr>
|
||||
<?php if(defined('TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED') && TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED) : ?>
|
||||
<tr>
|
||||
<td class="feldtitel">Externe Überwachnung</td>
|
||||
<td>
|
||||
<input type="checkbox" id="externe_ueberwachung" name="externe_ueberwachung"<?php echo $reihungstest->externe_ueberwachung ? 'checked="checked"' : '' ?>>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<tr>
|
||||
<td> </td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user