mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-10-12 06:54:04 +00:00
Merge branch 'master' into feature-78257/StudVW_Finetuning
This commit is contained in:
@@ -197,3 +197,11 @@ $config['unterbrechung_enabled'] = true;
|
||||
*/
|
||||
$config['wiederholung_enabled'] = true;
|
||||
|
||||
/**
|
||||
* Modal with Infotext of TLC
|
||||
* if true, there will be shown an info modal in the studentsView after the first button ABMELDUNG
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
$config['showInfoModalAbmeldung'] = true;
|
||||
|
||||
|
||||
@@ -177,6 +177,8 @@ $config['stv_prestudent_tags'] = [
|
||||
'unterbrecher_auto' => ['readonly' => true],
|
||||
'stbtr_erh_auto' => ['readonly' => true],
|
||||
'jgv_auto' => ['readonly' => true],
|
||||
'in_auto' => ['readonly' => true],
|
||||
'preabbr_auto' => ['readonly' => true],
|
||||
];
|
||||
|
||||
$config['userAutomatedTags'] = 'sftest';
|
||||
|
||||
@@ -22,10 +22,10 @@ if (!defined('BASEPATH')) exit('No direct script access allowed');
|
||||
$config['root'] = [
|
||||
'stg' => [
|
||||
'semester' => [
|
||||
/*'group',
|
||||
'group',
|
||||
'verband' => [
|
||||
'group'
|
||||
]*/
|
||||
]
|
||||
],
|
||||
'orgform'
|
||||
]
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 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/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* This controller operates between (interface) the JS (GUI) and the PhrasesLib (back-end)
|
||||
* Provides data to the ajax get calls about the Phrasen plugin
|
||||
* This controller works with JSON calls on the HTTP GET and the output is always JSON
|
||||
*/
|
||||
class TabulatorPresets extends FHCAPI_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getTabulatorPresets' => self::PERM_LOGGED,
|
||||
'createTabulatorPreset' => self::PERM_LOGGED,
|
||||
'updateTabulatorPreset' => self::PERM_LOGGED,
|
||||
'deleteTabulatorPreset' => self::PERM_LOGGED,
|
||||
]);
|
||||
|
||||
$this->load->model('tabulator/Tabulator_preset_model', 'TabulatorPresetModel');
|
||||
|
||||
$this->loadPhrases([
|
||||
'global',
|
||||
'tabulator_presets'
|
||||
]);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
public function getTabulatorPresets()
|
||||
{
|
||||
$tableName = $this->input->get("tableName");
|
||||
if (!$tableName) {
|
||||
$this->terminateWithError(error($this->p->t("tabulator_presets", "invalid_params_err_msg")));
|
||||
}
|
||||
|
||||
$uid = getAuthUID();
|
||||
$presets = $this->TabulatorPresetModel->getTabulatorPresetsByUserAndTable($uid, $tableName);
|
||||
$presetsData = $this->getDataOrTerminateWithError($presets) ?? [];
|
||||
|
||||
$this->terminateWithSuccess($presetsData);
|
||||
}
|
||||
|
||||
public function createTabulatorPreset()
|
||||
{
|
||||
$tableName = $this->input->post("tableName");
|
||||
$presetName = $this->input->post("presetName");
|
||||
$preset = $this->input->post("preset");
|
||||
|
||||
if (!$tableName || !$presetName || !$preset) {
|
||||
$this->terminateWithError($this->p->t("tabulator_presets", "invalid_params_err_msg"), "general", 400);
|
||||
}
|
||||
|
||||
$uid = getAuthUID();
|
||||
|
||||
$existingPresetsResult = $this->TabulatorPresetModel->getTabulatorPresetsByUserAndTable($uid, $tableName);
|
||||
$existingPresets = $this->getDataOrTerminateWithError($existingPresetsResult) ?? [];
|
||||
|
||||
if (count($existingPresets) > 19) {
|
||||
$this->terminateWithError($this->p->t("tabulator_presets", "max_presets_count_err_msg"), "general", 409);
|
||||
}
|
||||
|
||||
$existingPresetNames = array_map(function($presetInfo) {
|
||||
return $presetInfo->preset_name;
|
||||
}, $existingPresets);
|
||||
|
||||
if (in_array($presetName, $existingPresetNames)) {
|
||||
$this->terminateWithError($this->p->t("tabulator_presets", "preset_name_duplicate_err_msg"), "general", 409);
|
||||
}
|
||||
|
||||
$presetCreationResult = $this->TabulatorPresetModel->createTabulatorPreset($uid, $tableName, $presetName, $preset);
|
||||
|
||||
if (isError($presetCreationResult)) {
|
||||
$this->terminateWithError($presetCreationResult->retval);
|
||||
}
|
||||
|
||||
$newPresetData = $this->TabulatorPresetModel->getTabulatorPreset($presetCreationResult->retval);
|
||||
$newPresetArray = $this->getDataOrTerminateWithError($newPresetData) ?? [null];
|
||||
$newPreset = $newPresetArray[0];
|
||||
|
||||
$this->terminateWithSuccess($newPreset);
|
||||
}
|
||||
|
||||
public function updateTabulatorPreset()
|
||||
{
|
||||
$presetId = $this->input->post("presetId");
|
||||
$preset = $this->input->post("preset");
|
||||
|
||||
if (!$presetId || !$preset) {
|
||||
$this->terminateWithError($this->p->t("tabulator_presets", "invalid_params_err_msg"), "general", 400);
|
||||
}
|
||||
|
||||
$existingPresetData = $this->TabulatorPresetModel->getTabulatorPreset($presetId);
|
||||
$existingPresetArray = $this->getDataOrTerminateWithError($existingPresetData) ?? [null];
|
||||
$existingPreset = $existingPresetArray[0];
|
||||
if (!$existingPreset) {
|
||||
$this->terminateWithError($this->p->t("tabulator_presets", "preset_not_found_err_msg"), "general", 404);
|
||||
}
|
||||
|
||||
$uid = getAuthUID();
|
||||
if ($existingPreset->benutzer_uid !== $uid) {
|
||||
$this->terminateWithError($this->p->t("tabulator_presets", "preset_not_own_update_err_msg"), "general", 403);
|
||||
}
|
||||
|
||||
$presetUpdateResult = $this->TabulatorPresetModel->updateTabulatorPreset($presetId, $preset);
|
||||
if (isError($presetUpdateResult)) {
|
||||
$this->terminateWithError($presetUpdateResult->retval);
|
||||
}
|
||||
|
||||
$updatedPresetData = $this->TabulatorPresetModel->getTabulatorPreset($presetId);
|
||||
$updatedPresetArray = $this->getDataOrTerminateWithError($updatedPresetData) ?? [null];
|
||||
$updatedPreset = $updatedPresetArray[0];
|
||||
|
||||
$this->terminateWithSuccess($updatedPreset);
|
||||
}
|
||||
|
||||
public function deleteTabulatorPreset()
|
||||
{
|
||||
$presetId = $this->input->post("presetId");
|
||||
if (!$presetId) {
|
||||
$this->terminateWithError($this->p->t("tabulator_presets", "invalid_params_err_msg"), "general", 400);
|
||||
}
|
||||
|
||||
$presetData = $this->TabulatorPresetModel->getTabulatorPreset($presetId);
|
||||
$presetArray = $this->getDataOrTerminateWithError($presetData) ?? [null];
|
||||
$preset = $presetArray[0];
|
||||
if (!$preset) {
|
||||
$this->terminateWithError($this->p->t("tabulator_presets", "preset_not_found_err_msg"), "general", 404);
|
||||
}
|
||||
|
||||
$uid = getAuthUID();
|
||||
if ($preset->benutzer_uid !== $uid) {
|
||||
$this->terminateWithError($this->p->t("tabulator_presets", "preset_not_own_delete_err_msg"), "general", 403);
|
||||
}
|
||||
|
||||
$presetDeletionResult = $this->TabulatorPresetModel->deleteTabulatorPreset($presetId);
|
||||
if (isError($presetDeletionResult)) {
|
||||
$this->terminateWithError($presetDeletionResult->retval);
|
||||
}
|
||||
|
||||
$this->terminateWithSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -756,6 +756,8 @@ class Students extends FHCAPI_Controller
|
||||
'studiensemester_kurzbz' => $studiensemester_kurzbz
|
||||
));
|
||||
|
||||
$studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
|
||||
|
||||
$this->load->library('SearchLib', [ 'config' => 'searchstv' ]);
|
||||
$this->load->library('form_validation');
|
||||
|
||||
|
||||
@@ -14,11 +14,11 @@ class Mylv extends Auth_Controller
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'Student' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions?
|
||||
'Studiensemester' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions?
|
||||
'Lvs' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions?
|
||||
'Info' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions?
|
||||
'Pruefungen' => ['student/anrechnung_beantragen:r','user:r'] // TODO(chris): permissions?
|
||||
'Student' => self::PERM_LOGGED,
|
||||
'Studiensemester' => self::PERM_LOGGED,
|
||||
'Lvs' => self::PERM_LOGGED,
|
||||
'Info' => self::PERM_LOGGED,
|
||||
'Pruefungen' => self::PERM_LOGGED
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ class AntragJob extends JOB_Controller
|
||||
$stgLeitungen[$leitung->uid]['stgs'][] = $antrag->studiengang_kz;
|
||||
}
|
||||
|
||||
$result = $this->StudierendenantragModel->getStgAndSem($antrag->studierendenantrag_id);
|
||||
$result = $this->StudierendenantragModel->getStgAndDetails($antrag->studierendenantrag_id);
|
||||
if (isError($result))
|
||||
{
|
||||
$this->logError(getError($result));
|
||||
|
||||
@@ -25,7 +25,8 @@ class Studierendenantrag extends FHC_Controller
|
||||
|
||||
// Load language phrases
|
||||
$this->loadPhrases([
|
||||
'studierendenantrag'
|
||||
'studierendenantrag',
|
||||
'ui'
|
||||
]);
|
||||
|
||||
$this->load->config('studierendenantrag');
|
||||
|
||||
@@ -349,16 +349,27 @@ class Tag_Controller extends FHCAPI_Controller
|
||||
|
||||
public function rebuildTagsForTypeId()
|
||||
{
|
||||
$id = $this->input->post('id');
|
||||
$ids = $this->input->post('ids');
|
||||
$typeId = $this->input->post('typeId');
|
||||
$semester = $this->input->post('sem');
|
||||
|
||||
$result = $this->taglib->rebuildTagsForTypeId($typeId, $id, $semester);
|
||||
$idsSuccess = [];
|
||||
$idsError = [];
|
||||
$outputResult = [];
|
||||
|
||||
if (isError($result))
|
||||
return error ('Error occurred during updateAutomatedTags');
|
||||
foreach ($ids as $id)
|
||||
{
|
||||
$result = $this->taglib->rebuildTagsForTypeId($typeId, $id, $semester);
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
if (isError($result))
|
||||
$idsError[] = $id;
|
||||
else
|
||||
$idsSuccess[] = $id;
|
||||
|
||||
$outputResult[] = $result;
|
||||
}
|
||||
|
||||
$this->terminateWithSuccess([$outputResult, $idsSuccess, $idsError]);
|
||||
}
|
||||
|
||||
private function _setAuthUID()
|
||||
@@ -401,4 +412,4 @@ class Tag_Controller extends FHCAPI_Controller
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +111,8 @@ function generateJSDataStorageObject($indexPage, $calledPath, $calledMethod)
|
||||
'theme' => [
|
||||
'name'=>$ci->config->item('theme_name'),
|
||||
'modes'=>$ci->config->item('theme_modes'),
|
||||
]
|
||||
],
|
||||
'domain' => DOMAIN
|
||||
);
|
||||
|
||||
$toPrint = "\n";
|
||||
|
||||
@@ -37,7 +37,7 @@ class TagLib
|
||||
$this->_ci->load->library('PermissionLib');
|
||||
$this->_ci->load->library('PrestudentLib');
|
||||
|
||||
$batchUser = $this->_ci->config->item('userAutomatedTags');
|
||||
$this->batchUser = $this->_ci->config->item('userAutomatedTags');
|
||||
}
|
||||
|
||||
public function updateAutomatedTags($paramsTag)
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* Description of out_auto
|
||||
*
|
||||
* @author ma0068
|
||||
*/
|
||||
class CoreIncomingTagLib
|
||||
{
|
||||
protected $ci;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->ci = get_instance();
|
||||
$this->ci->load->model('codex/Bisio_model', 'BisioModel');
|
||||
}
|
||||
|
||||
public function getZuordnungIds(array $params)
|
||||
{
|
||||
if(!isset($params['studiensemester_kurzbz']))
|
||||
{
|
||||
return (object) array(
|
||||
'idArray' => []
|
||||
);
|
||||
}
|
||||
|
||||
$semester = $params['studiensemester_kurzbz'];
|
||||
|
||||
$result = $this->ci->BisioModel->getIncomingsOfSemester($semester);
|
||||
|
||||
$data = $result->retval;
|
||||
|
||||
$outgoing_data = array_map(function($item) {
|
||||
return [
|
||||
'id' => $item->prestudent_id,
|
||||
'von' => $item->von,
|
||||
'bis' => $item->bis
|
||||
];
|
||||
}, $data);
|
||||
|
||||
return (object) array(
|
||||
'data' => $outgoing_data,
|
||||
'typeId' => 'prestudent_id',
|
||||
);
|
||||
}
|
||||
|
||||
public function isCriteriaSetFor(array $params)
|
||||
{
|
||||
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id')
|
||||
return false;
|
||||
|
||||
$semester = $params['studiensemester_kurzbz'];
|
||||
$prestudent_id = $params['id'];
|
||||
|
||||
$result = $this->ci->BisioModel->isPrestudentIncoming($semester, $prestudent_id);
|
||||
|
||||
if (hasData($result)) {
|
||||
return $result;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
/**
|
||||
* Description of prewh_auto
|
||||
*
|
||||
* @author ma0068
|
||||
*/
|
||||
class CorePreabbrecherTagLib
|
||||
{
|
||||
protected $ci;
|
||||
const TYP_ABMELDUNG = ['Abmeldung', 'AbmeldungStgl'];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->ci = get_instance();
|
||||
$this->ci->load->model('education/Studierendenantrag_model', 'StudierendenantragModel');
|
||||
}
|
||||
|
||||
public function getZuordnungIds(array $params)
|
||||
{
|
||||
if(!isset($params['studiensemester_kurzbz']))
|
||||
{
|
||||
return (object) array(
|
||||
'idArray' => []
|
||||
);
|
||||
}
|
||||
|
||||
$semester = $params['studiensemester_kurzbz'];
|
||||
|
||||
$this->ci->StudierendenantragModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
|
||||
$this->ci->StudierendenantragModel->db->where_in('typ', self::TYP_ABMELDUNG);
|
||||
$this->ci->StudierendenantragModel->db->where('studiensemester_kurzbz', $semester);
|
||||
$result = $this->ci->StudierendenantragModel->getWithLastStatusWhere([
|
||||
'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_CREATED
|
||||
]);
|
||||
|
||||
$data = $result->retval;
|
||||
|
||||
$prewiederholer_data = array_map(function($item) {
|
||||
return [
|
||||
'id' => $item->prestudent_id,
|
||||
'von' => $item->start,
|
||||
'bis' => $item->ende
|
||||
];
|
||||
}, $data);
|
||||
|
||||
return (object) array(
|
||||
'data' => $prewiederholer_data,
|
||||
'typeId' => 'prestudent_id',
|
||||
);
|
||||
}
|
||||
|
||||
public function isCriteriaSetFor(array $params)
|
||||
{
|
||||
if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id')
|
||||
return false;
|
||||
|
||||
$semester = $params['studiensemester_kurzbz'];
|
||||
$prestudent_id = $params['id'];
|
||||
|
||||
$this->ci->StudierendenantragModel->addSelect('prestudent_id');
|
||||
$this->ci->StudierendenantragModel->addSelect('start as von');
|
||||
$this->ci->StudierendenantragModel->addSelect('ende as bis');
|
||||
|
||||
$this->ci->StudierendenantragModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
|
||||
$this->ci->StudierendenantragModel->db->where_in('typ', self::TYP_ABMELDUNG);
|
||||
$this->ci->StudierendenantragModel->db->where('studiensemester_kurzbz', $semester);
|
||||
$this->ci->StudierendenantragModel->db->where('prestudent_id', $prestudent_id);
|
||||
$result = $this->ci->StudierendenantragModel->getWithLastStatusWhere([
|
||||
'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_CREATED
|
||||
]);
|
||||
|
||||
if(hasData($result))
|
||||
{
|
||||
return $result;
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -73,6 +73,34 @@ class Bisio_model extends DB_Model
|
||||
return $this->execQuery($query, array($studiensemester_kurzbz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets incoming students of certain Semester
|
||||
* @param String studiensemester_kurzbz
|
||||
* @return array of prestudent_ids
|
||||
*/
|
||||
public function getIncomingsOfSemester($studiensemester_kurzbz)
|
||||
{
|
||||
$query = "
|
||||
SELECT DISTINCT ps.prestudent_id, tbl_bisio.von, tbl_bisio.bis
|
||||
FROM bis.tbl_bisio
|
||||
JOIN public.tbl_student USING (student_uid)
|
||||
JOIN public.tbl_prestudent ps USING (prestudent_id)
|
||||
JOIN public.tbl_prestudentstatus pss ON (ps.prestudent_id = pss.prestudent_id)
|
||||
JOIN public.tbl_studiensemester ss ON (pss.studiensemester_kurzbz = ss.studiensemester_kurzbz)
|
||||
WHERE ss.studiensemester_kurzbz = ?
|
||||
AND nation_code = 'A'
|
||||
AND (
|
||||
tbl_bisio.von <= ss.ende
|
||||
AND (
|
||||
tbl_bisio.bis >= ss.start
|
||||
OR tbl_bisio.bis IS NULL
|
||||
)
|
||||
)
|
||||
";
|
||||
|
||||
return $this->execQuery($query, array($studiensemester_kurzbz));
|
||||
}
|
||||
|
||||
public function isPrestudentOutgoing($studiensemester_kurzbz, $prestudent_id)
|
||||
{
|
||||
$query = "
|
||||
@@ -97,4 +125,29 @@ class Bisio_model extends DB_Model
|
||||
|
||||
return $this->execQuery($query, array($studiensemester_kurzbz, $prestudent_id));
|
||||
}
|
||||
|
||||
public function isPrestudentIncoming($studiensemester_kurzbz, $prestudent_id)
|
||||
{
|
||||
$query = "
|
||||
SELECT
|
||||
ps.prestudent_id, tbl_bisio.von, tbl_bisio.bis
|
||||
FROM bis.tbl_bisio
|
||||
JOIN public.tbl_student USING (student_uid)
|
||||
JOIN public.tbl_prestudent ps USING (prestudent_id)
|
||||
JOIN public.tbl_prestudentstatus pss ON (ps.prestudent_id = pss.prestudent_id)
|
||||
JOIN public.tbl_studiensemester ss ON (pss.studiensemester_kurzbz = ss.studiensemester_kurzbz)
|
||||
WHERE ss.studiensemester_kurzbz = ?
|
||||
AND nation_code = 'A'
|
||||
AND (
|
||||
tbl_bisio.von <= ss.ende
|
||||
AND (
|
||||
tbl_bisio.bis >= ss.start
|
||||
OR tbl_bisio.bis IS NULL
|
||||
)
|
||||
)
|
||||
AND ps.prestudent_id = ?
|
||||
";
|
||||
|
||||
return $this->execQuery($query, array($studiensemester_kurzbz, $prestudent_id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,6 +188,7 @@ class Studierendenantrag_model extends DB_Model
|
||||
* Get the studiengang and ausbildungssemester the student was in
|
||||
* for the studiensemester the antrag was committed for
|
||||
*
|
||||
*
|
||||
* @param integer $antrag_id
|
||||
*
|
||||
* @return stdClass
|
||||
@@ -242,6 +243,28 @@ class Studierendenantrag_model extends DB_Model
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the studiengang and the studienplan the student is in
|
||||
*
|
||||
* @param integer $antrag_id
|
||||
*
|
||||
* @return stdClass
|
||||
*/
|
||||
public function getStgAndDetails($antrag_id)
|
||||
{
|
||||
$this->addSelect('p.studiengang_kz');
|
||||
$this->addSelect('stg.orgform_kurzbz');
|
||||
$this->addSelect('stg.bezeichnung');
|
||||
$this->addJoin('public.tbl_prestudent p', 'prestudent_id');
|
||||
$this->addJoin('public.tbl_studiengang stg', 'studiengang_kz');
|
||||
|
||||
$this->addLimit(1);
|
||||
|
||||
return $this->load(
|
||||
$antrag_id
|
||||
);
|
||||
}
|
||||
|
||||
public function getStgEmail($antrag_id)
|
||||
{
|
||||
$this->addJoin('public.tbl_prestudent p', 'prestudent_id');
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
class Tabulator_preset_model extends DB_Model
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dbTable = 'public.tbl_tabulator_presets';
|
||||
$this->pk = ['preset_id'];
|
||||
$this->hasSequence = true;
|
||||
|
||||
|
||||
$this->load->model('person/Benutzer_model', 'BenutzerModel');
|
||||
}
|
||||
|
||||
public function getTabulatorPreset($presetId)
|
||||
{
|
||||
$query = "
|
||||
SELECT *
|
||||
FROM public.tbl_tabulator_presets
|
||||
WHERE preset_id = ?
|
||||
LIMIT 1
|
||||
";
|
||||
return $this->execQuery($query, array($presetId));
|
||||
}
|
||||
|
||||
public function getTabulatorPresetsByUserAndTable($uid, $tableName)
|
||||
{
|
||||
$query = '
|
||||
SELECT *
|
||||
FROM public.tbl_tabulator_presets
|
||||
WHERE benutzer_uid = ?
|
||||
AND table_name = ?
|
||||
ORDER BY preset_id ASC
|
||||
';
|
||||
return $this->execQuery($query, array($uid, $tableName));
|
||||
}
|
||||
|
||||
public function createTabulatorPreset($uid, $tableName, $presetName, $preset)
|
||||
{
|
||||
$presetCreationResult = $this->insert([
|
||||
"benutzer_uid" => $uid,
|
||||
"table_name" => $tableName,
|
||||
"preset_name" => $presetName,
|
||||
"preset_json" => json_encode($preset),
|
||||
]);
|
||||
|
||||
if (isError($presetCreationResult))
|
||||
{
|
||||
return error('Something went wrong during preset creation!');
|
||||
}
|
||||
|
||||
return success($presetCreationResult->retval);
|
||||
}
|
||||
|
||||
public function updateTabulatorPreset($presetId, $preset)
|
||||
{
|
||||
$presetUpdateResult = $this->update(["preset_id" => $presetId], ["preset_json" => json_encode($preset)]);
|
||||
|
||||
if (isError($presetUpdateResult))
|
||||
{
|
||||
return error('Something went wrong during preset update!');
|
||||
}
|
||||
|
||||
return success($presetUpdateResult->retval);
|
||||
}
|
||||
|
||||
public function deleteTabulatorPreset($presetId)
|
||||
{
|
||||
$presetDeletionReseult = $this->delete(["preset_id" => $presetId]);
|
||||
|
||||
if (isError($presetDeletionReseult))
|
||||
{
|
||||
return error('Something went wrong during preset deletion!');
|
||||
}
|
||||
|
||||
return success($presetDeletionReseult->retval);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -56,12 +56,13 @@ $configArray = [
|
||||
<router-view
|
||||
default-semester="<?= $variables['semester_aktuell']; ?>"
|
||||
active-addons="<?= defined('ACTIVE_ADDONS') ? ACTIVE_ADDONS : ''; ?>"
|
||||
stv-root="<?= site_url('Studentenverwaltung'); ?>"
|
||||
stv-root="<?= site_url('studvw'); ?>"
|
||||
cis-root="<?= CIS_ROOT; ?>"
|
||||
avatar-url="<?= site_url('Cis/Pub/bild/person/' . getAuthPersonId()); ?>"
|
||||
logout-url="<?= site_url('Cis/Auth/logout'); ?>"
|
||||
:permissions="<?= htmlspecialchars(json_encode($permissions)); ?>"
|
||||
:config="<?= htmlspecialchars(json_encode($configArray)); ?>"
|
||||
auth-uid="<?= getAuthUID()?>"
|
||||
>
|
||||
</router-view>
|
||||
</div>
|
||||
|
||||
@@ -30,6 +30,12 @@ if(defined('CIS4')){
|
||||
}
|
||||
?>
|
||||
|
||||
<?php
|
||||
|
||||
$config = $this->load->config('studierendenantrag');
|
||||
$showInfoModalAbmeldung = $this->config->item('showInfoModalAbmeldung');
|
||||
?>
|
||||
|
||||
<div id="wrapper">
|
||||
|
||||
<div class="fhc-header">
|
||||
@@ -43,17 +49,75 @@ if(defined('CIS4')){
|
||||
<h4><?= $array['bezeichnungStg']; ?> (<?= $array['bezeichnungOrgform']; ?>)</h4>
|
||||
|
||||
<?php foreach ($array['allowedNewTypes'] as $type) { ?>
|
||||
|
||||
<div class="alert alert-secondary">
|
||||
<p><?= $this->p->t('studierendenantrag', 'calltoaction_' . $type); ?></p>
|
||||
<hr>
|
||||
<a
|
||||
href="<?= site_url('lehre/Studierendenantrag/' . strtolower($type) . '/' . $prestudent_id); ?>"
|
||||
class="btn btn-outline-secondary"
|
||||
>
|
||||
<i class="fa fa-plus"></i> <?= $this->p->t('studierendenantrag', 'antrag_typ_' . $type); ?>
|
||||
</a>
|
||||
<p><?= $this->p->t('studierendenantrag', 'calltoaction_' . $type); ?></p>
|
||||
<hr>
|
||||
<?php
|
||||
if($type == 'Abmeldung' && $showInfoModalAbmeldung){
|
||||
$href = "#modalinfo" . $prestudent_id;
|
||||
}
|
||||
else
|
||||
$href = site_url('lehre/Studierendenantrag/' . strtolower($type) . '/' . $prestudent_id);
|
||||
?>
|
||||
|
||||
<a
|
||||
href="<?= $href ?>"
|
||||
class="btn btn-outline-secondary"
|
||||
<?php if($type == 'Abmeldung' && $showInfoModalAbmeldung): ?>
|
||||
data-bs-toggle="modal"
|
||||
<?php endif; ?>
|
||||
>
|
||||
<i class="fa fa-plus"></i> <?= $this->p->t('studierendenantrag', 'antrag_typ_' . $type); ?>
|
||||
</a>
|
||||
|
||||
<!-- Modal -->
|
||||
<div
|
||||
class="modal fade"
|
||||
id="modalinfo<?= $prestudent_id; ?>"
|
||||
tabindex="-1"
|
||||
aria-labelledby="modalinfoLabel<?= $prestudent_id; ?>"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="modal-dialog modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5
|
||||
class="modal-title"
|
||||
id="modalinfoLabel<?= $prestudent_id; ?>"
|
||||
> <?= $this->p->t('studierendenantrag', 'info_consultation'); ?>
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<?php
|
||||
$hrefUnterbrechung = site_url('lehre/Studierendenantrag/unterbrechung/' . $prestudent_id);
|
||||
?>
|
||||
<div class="modal-body">
|
||||
<div
|
||||
class="form-control"
|
||||
style="width: 100%; height: 250px;overflow:auto; white-space: normal;"
|
||||
><?= $this->p->t('studierendenantrag', 'modalHinweistext_Abmeldung', ['linkUnterbrechung' => $hrefUnterbrechung] ); ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-primary" data-bs-dismiss="modal"><?= $this->p->t('ui', 'cancel'); ?></button>
|
||||
<a
|
||||
href="<?= site_url('lehre/Studierendenantrag/abmeldung/' . $prestudent_id); ?>"
|
||||
class="btn btn-outline-primary"
|
||||
> <?= $this->p->t('studierendenantrag', 'link_Abmeldung'); ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
|
||||
<?php } ?>
|
||||
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
@@ -205,7 +269,7 @@ if(defined('CIS4')){
|
||||
</a>
|
||||
<lv-popup
|
||||
id="modallv<?= $antrag->studierendenantrag_id; ?>"
|
||||
antrag-id = "<?= $antrag->studierendenantrag_id; ?>"
|
||||
:antrag-id = "<?= $antrag->studierendenantrag_id; ?>"
|
||||
>
|
||||
<?= $this->p->t('studierendenantrag', 'my_lvs'); ?>
|
||||
</lv-popup>
|
||||
|
||||
@@ -154,6 +154,7 @@
|
||||
generateJSsInclude('vendor/npm-asset/primevue/confirmdialog/confirmdialog.min.js');
|
||||
generateJSsInclude('vendor/npm-asset/primevue/confirmationservice/confirmationservice.min.js');
|
||||
generateJSsInclude('vendor/npm-asset/primevue/tieredmenu/tieredmenu.min.js');
|
||||
generateJSsInclude('vendor/npm-asset/primevue/progressbar/progressbar.min.js');
|
||||
}
|
||||
|
||||
if($vuedatepicker11) generateJSsInclude('vendor/vuejs/vuedatepicker_js11/vue-datepicker.iife.js');
|
||||
|
||||
+4
-4
@@ -109,9 +109,9 @@
|
||||
"type": "package",
|
||||
"package": {
|
||||
"name": "fortawesome/font-awesome6",
|
||||
"version": "6.1.1",
|
||||
"version": "6.7.2",
|
||||
"dist": {
|
||||
"url": "https://github.com/FortAwesome/Font-Awesome/archive/refs/tags/6.1.1.zip",
|
||||
"url": "https://github.com/FortAwesome/Font-Awesome/archive/refs/tags/6.7.2.zip",
|
||||
"type": "zip"
|
||||
}
|
||||
}
|
||||
@@ -468,7 +468,7 @@
|
||||
|
||||
"fgelinas/timepicker": "0.3.3",
|
||||
"fortawesome/font-awesome4": "4.7.*",
|
||||
"fortawesome/font-awesome6": "6.1.*",
|
||||
"fortawesome/font-awesome6": "6.7.*",
|
||||
"fzaninotto/faker": "1.*",
|
||||
"firebase/php-jwt": "^6.0",
|
||||
|
||||
@@ -496,7 +496,7 @@
|
||||
"netcarver/textile": "3.7.*",
|
||||
"nicolaskruchten/pivottable": "2.23.0",
|
||||
"npm-asset/primevue": "3.29.1",
|
||||
"npm-asset/primeicons": "5.0.0",
|
||||
"npm-asset/primeicons": "6.0.1",
|
||||
|
||||
"olifolkerd/tabulator4": "4.9.*",
|
||||
"olifolkerd/tabulator5": "5.5.*",
|
||||
|
||||
Generated
+5
-5
@@ -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": "869cbc35bd1ba90ab90934fcb41b0f51",
|
||||
"content-hash": "bc21de2a48b960781c1ed028c4b8d7b9",
|
||||
"packages": [
|
||||
{
|
||||
"name": "afarkas/html5shiv",
|
||||
@@ -960,10 +960,10 @@
|
||||
},
|
||||
{
|
||||
"name": "fortawesome/font-awesome6",
|
||||
"version": "6.1.1",
|
||||
"version": "6.7.2",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://github.com/FortAwesome/Font-Awesome/archive/refs/tags/6.1.1.zip"
|
||||
"url": "https://github.com/FortAwesome/Font-Awesome/archive/refs/tags/6.7.2.zip"
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
@@ -1565,10 +1565,10 @@
|
||||
},
|
||||
{
|
||||
"name": "npm-asset/primeicons",
|
||||
"version": "5.0.0",
|
||||
"version": "6.0.1",
|
||||
"dist": {
|
||||
"type": "tar",
|
||||
"url": "https://registry.npmjs.org/primeicons/-/primeicons-5.0.0.tgz"
|
||||
"url": "https://registry.npmjs.org/primeicons/-/primeicons-6.0.1.tgz"
|
||||
},
|
||||
"type": "npm-asset",
|
||||
"license": [
|
||||
|
||||
@@ -91,6 +91,15 @@
|
||||
color: black;
|
||||
}
|
||||
|
||||
.tag_skyblue {
|
||||
background-color: #90D5FF;
|
||||
color: black;
|
||||
}
|
||||
.tag_blush {
|
||||
background-color: #A83E3E;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.tag_done {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* Copyright (C) 2025 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
getTabulatorPresets(tableName) {
|
||||
return {
|
||||
method: "get",
|
||||
url:
|
||||
"/api/frontend/v1/TabulatorPresets/getTabulatorPresets?tableName=" +
|
||||
tableName,
|
||||
};
|
||||
},
|
||||
createTabulatorPreset(tableName, presetName, preset) {
|
||||
return {
|
||||
method: "post",
|
||||
url: "/api/frontend/v1/TabulatorPresets/createTabulatorPreset",
|
||||
params: {
|
||||
tableName,
|
||||
presetName,
|
||||
preset,
|
||||
},
|
||||
};
|
||||
},
|
||||
updateTabulatorPreset(presetId, preset) {
|
||||
return {
|
||||
method: "post",
|
||||
url: "/api/frontend/v1/TabulatorPresets/updateTabulatorPreset",
|
||||
params: {
|
||||
presetId,
|
||||
preset,
|
||||
},
|
||||
};
|
||||
},
|
||||
deleteTabulatorPreset(tabulatorPresetId) {
|
||||
return {
|
||||
method: "post",
|
||||
url:
|
||||
"/api/frontend/v1/TabulatorPresets/deleteTabulatorPreset",
|
||||
params: {
|
||||
presetId: tabulatorPresetId,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
@@ -469,6 +469,7 @@ export default {
|
||||
:tabulator-options="betriebsmittel_table_options"
|
||||
tableOnly
|
||||
:sideMenu="false"
|
||||
:isUsingPresets="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -43,6 +43,7 @@ export default {
|
||||
maxWidth: 40,
|
||||
headerClick: this.collapseFunction,
|
||||
visible: true,
|
||||
responsive: 0,
|
||||
},
|
||||
{
|
||||
title: "placeholder",
|
||||
@@ -51,6 +52,7 @@ export default {
|
||||
headerFilter: true,
|
||||
minWidth: 200,
|
||||
visible: true,
|
||||
responsive: 0,
|
||||
},
|
||||
{
|
||||
title: "placeholder",
|
||||
@@ -59,6 +61,7 @@ export default {
|
||||
headerFilter: true,
|
||||
minWidth: 200,
|
||||
visible: true,
|
||||
responsive: 1,
|
||||
},
|
||||
{
|
||||
title: "placeholder",
|
||||
@@ -71,6 +74,7 @@ export default {
|
||||
visible: true,
|
||||
formatter: "datetime",
|
||||
formatterParams: this.datetimeFormatterParams(),
|
||||
responsive: 4,
|
||||
},
|
||||
{
|
||||
title: "placeholder",
|
||||
@@ -83,6 +87,7 @@ export default {
|
||||
visible: true,
|
||||
formatter: "datetime",
|
||||
formatterParams: this.datetimeFormatterParams(),
|
||||
responsive: 3,
|
||||
},
|
||||
{
|
||||
title: "placeholder",
|
||||
@@ -91,6 +96,7 @@ export default {
|
||||
headerFilter: true,
|
||||
minWidth: 200,
|
||||
visible: true,
|
||||
responsive: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -176,7 +176,6 @@ export const Profil = {
|
||||
this.data = data.profil_data.data;
|
||||
this.calendarSyncUrls = data.calendar_sync_urls ?? [];
|
||||
this.authPermissions = data.permissions;
|
||||
console.log(data.profil_data);
|
||||
},
|
||||
zustellAdressenCount() {
|
||||
if (!this.data || !this.data.adressen) {
|
||||
|
||||
@@ -326,8 +326,10 @@ export default {
|
||||
this.reload();
|
||||
},
|
||||
rebuildPrestudentTags(){
|
||||
const id = [this.headerData[0].prestudent_id];
|
||||
|
||||
const params = {
|
||||
id : this.headerData[0].prestudent_id,
|
||||
ids: id,
|
||||
typeId: 'prestudent_id',
|
||||
sem: this.currentSemester
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@ import BaseTreemenu from '../Base/Treemenu.js';
|
||||
import StvStudiensemester from "../Stv/Studentenverwaltung/Studiensemester.js";
|
||||
import LvTable from "./Setup/Table.js";
|
||||
import LvTabs from "./Setup/Tabs.js";
|
||||
import NavLanguage from "../navigation/Language.js";
|
||||
|
||||
import ApiDetails from "../../api/lehrveranstaltung/details.js";
|
||||
import ApiLektor from "../../api/lehrveranstaltung/lektor.js";
|
||||
@@ -25,7 +26,8 @@ export default {
|
||||
StvStudiensemester,
|
||||
LvTable,
|
||||
LvTabs,
|
||||
AppConfig
|
||||
AppConfig,
|
||||
NavLanguage
|
||||
},
|
||||
props: {
|
||||
avatarUrl: String,
|
||||
@@ -47,10 +49,13 @@ export default {
|
||||
permissionLehrveranstaltung: this.permissions['lehre/lehrveranstaltung'],
|
||||
permissionGruppenEntfernen: this.permissions['lv-plan/gruppenentfernen'],
|
||||
permissionLektorEntfernen: this.permissions['lv-plan/lektorentfernen'],
|
||||
language: Vue.computed(() => this.$p.user_language),
|
||||
isMobile: false,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
sidebarCollapsed: false,
|
||||
appconfig:{},
|
||||
configEndpoints: ApiLvConfig,
|
||||
selected: [],
|
||||
|
||||
@@ -25,18 +25,34 @@ export default {
|
||||
return {
|
||||
stdsem: '',
|
||||
endpoint: ApiLVNoten,
|
||||
tabulatorOptions: {
|
||||
tabulatorOptionsZeugnis: {
|
||||
visibleColumns: {
|
||||
vorname: true,
|
||||
nachname: true,
|
||||
uid: true,
|
||||
lehrveranstaltung_bezeichnung: false
|
||||
},
|
||||
headerFilter: {
|
||||
vorname: true,
|
||||
nachname: true,
|
||||
uid: true,
|
||||
lehrveranstaltung_bezeichnung: false
|
||||
},
|
||||
persistenceZeugnisID: 'lv-details-noten-zeugnis-2025120401',
|
||||
},
|
||||
tabulatorOptionsTeacher: {
|
||||
visibleColumns: {
|
||||
vorname: true,
|
||||
nachname: true,
|
||||
student_uid: true,
|
||||
lehrveranstaltung_bezeichnung: false
|
||||
},
|
||||
headerFilter: {
|
||||
vorname: true,
|
||||
nachname: true,
|
||||
student_uid: true,
|
||||
lehrveranstaltung_bezeichnung: false
|
||||
},
|
||||
persistenceTeacherID: 'lv-details-noten-teacher-2025120401',
|
||||
},
|
||||
zeugnisLoaded: false,
|
||||
@@ -98,7 +114,7 @@ export default {
|
||||
:id="modelValue.lehrveranstaltung_id"
|
||||
:all-semester="!!stdsem"
|
||||
:endpoint="endpoint"
|
||||
:optionalTabulatorOptions="tabulatorOptions"
|
||||
:optionalTabulatorOptions="tabulatorOptionsZeugnis"
|
||||
@loaded="onZeugnisLoaded"/>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
@@ -108,7 +124,7 @@ export default {
|
||||
:all-semester="!!stdsem"
|
||||
:endpoint="endpoint"
|
||||
@copied="reload"
|
||||
:optionalTabulatorOptions="tabulatorOptions"
|
||||
:optionalTabulatorOptions="tabulatorOptionsTeacher"
|
||||
@loaded="onTeacherLoaded"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -54,7 +54,8 @@ export default {
|
||||
cisRoot: String,
|
||||
avatarUrl: String,
|
||||
logoutUrl: String,
|
||||
activeAddons: String // semicolon separated list of active addons
|
||||
activeAddons: String, // semicolon separated list of active addons
|
||||
authUid: String
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
@@ -88,7 +89,9 @@ export default {
|
||||
hasZGVMasterPermission: this.permissions['student/editMakkZgv'],
|
||||
hasZGVDoctorPermission: this.permissions['student/editDokZgv'],
|
||||
hasBismeldenPermission: this.permissions['student/editBismelden'],
|
||||
|
||||
authUid: this.authUid,
|
||||
language: Vue.computed(() => this.$p.user_language),
|
||||
isMobile: false,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -216,6 +219,28 @@ export default {
|
||||
|
||||
return extraItems;
|
||||
},
|
||||
appMenuBisItems() {
|
||||
const extraItems = [];
|
||||
|
||||
if (this.studiengangKz !== undefined) {
|
||||
const studiengang_kz = String(this.studiengangKz);
|
||||
|
||||
extraItems.push({
|
||||
link: FHC_JS_DATA_STORAGE_OBJECT.app_root
|
||||
+ 'vilesci/bis/studentenmeldung.php?'
|
||||
+ 'stg_kz=' + studiengang_kz,
|
||||
description: 'stv/bis_stud_meldung'
|
||||
});
|
||||
extraItems.push({
|
||||
link: FHC_JS_DATA_STORAGE_OBJECT.app_root
|
||||
+ 'system/checkStudenten.php?'
|
||||
+ 'stg_kz=' + studiengang_kz,
|
||||
description: 'stv/bis_stud_plausicheck'
|
||||
});
|
||||
}
|
||||
|
||||
return extraItems;
|
||||
},
|
||||
linkRt(){
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + '/vilesci/stammdaten/reihungstestverwaltung.php'
|
||||
},
|
||||
@@ -289,6 +314,11 @@ export default {
|
||||
sidebarCollapsed(newVal) {
|
||||
if(newVal) this.$refs.hSplit.collapseLeft()
|
||||
else this.$refs.hSplit.showBoth()
|
||||
},
|
||||
studiengangKz(newVal, oldVal) {
|
||||
if (newVal !== oldVal) {
|
||||
this.$refs.stvList.clearSelection();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -401,6 +431,9 @@ export default {
|
||||
showAlertNoGroupChosen(){
|
||||
this.$fhcAlert.alertError(this.$p.t('ui', 'alert_chooseGroupSem'));
|
||||
},
|
||||
showAlertNoDegreeProgramChosen(){
|
||||
this.$fhcAlert.alertError(this.$p.t('ui', 'alert_chooseDegreeProgram'));
|
||||
},
|
||||
showMenu(refName) {
|
||||
bootstrap.Dropdown.getOrCreateInstance(this.$refs[refName]).show();
|
||||
},
|
||||
@@ -613,13 +646,13 @@ export default {
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li :class="{ dropend: appMenuExtraItems.length }"
|
||||
@mouseenter="appMenuExtraItems.length && showMenu('lvPlanungToggle')"
|
||||
@mouseleave="appMenuExtraItems.length && hideMenu('lvPlanungToggle')"
|
||||
<li :class="{ dropend: appMenuLvPlanungItems.length }"
|
||||
@mouseenter="appMenuLvPlanungItems.length && showMenu('lvPlanungToggle')"
|
||||
@mouseleave="appMenuLvPlanungItems.length && hideMenu('lvPlanungToggle')"
|
||||
>
|
||||
<a
|
||||
ref="lvPlanungToggle"
|
||||
v-if="appMenuExtraItems.length"
|
||||
v-if="appMenuLvPlanungItems.length"
|
||||
class="dropdown-toggle"
|
||||
href="#"
|
||||
role="button"
|
||||
@@ -636,7 +669,7 @@ export default {
|
||||
>
|
||||
{{ $p.t('stv/lvplanung') }}
|
||||
</a>
|
||||
<ul v-if="appMenuExtraItems.length" class="dropdown-menu p-0">
|
||||
<ul v-if="appMenuLvPlanungItems.length" class="dropdown-menu p-0">
|
||||
<li
|
||||
v-for="(item, key) in appMenuLvPlanungItems"
|
||||
:key="key"
|
||||
@@ -663,6 +696,42 @@ export default {
|
||||
{{ $p.t('stv/studienverlauf') }}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li :class="{ dropend: appMenuBisItems.length }"
|
||||
@mouseenter="appMenuBisItems.length && showMenu('bisToggle')"
|
||||
@mouseleave="appMenuBisItems.length && hideMenu('bisToggle')"
|
||||
>
|
||||
<a
|
||||
ref="bisToggle"
|
||||
v-if="appMenuBisItems.length"
|
||||
class="dropdown-toggle"
|
||||
href="#"
|
||||
role="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
data-bs-popper-config='{"strategy":"fixed"}'
|
||||
>
|
||||
{{ $p.t('stv/bis_stud') }}
|
||||
</a>
|
||||
<a
|
||||
v-else
|
||||
href="#"
|
||||
@click.prevent="showAlertNoDegreeProgramChosen"
|
||||
>
|
||||
{{ $p.t('stv/bis_stud') }}
|
||||
</a>
|
||||
<ul v-if="appMenuBisItems.length" class="dropdown-menu p-0">
|
||||
<li
|
||||
v-for="(item, key) in appMenuBisItems"
|
||||
:key="key"
|
||||
>
|
||||
<a class="dropdown-item" :href="item.link" target="_blank">
|
||||
{{ $p.t(item.description) }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</app-menu>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
@@ -402,7 +402,7 @@ export default {
|
||||
name="foto"
|
||||
@actionbutton-clicked="sendInfomail"
|
||||
>
|
||||
<img alt="No Image" :src="noImageSrc" class="w-100">
|
||||
<img alt="No Image" :src="noImageSrc" />
|
||||
</form-input>
|
||||
<form-input
|
||||
v-if="!config.hiddenFields.includes('anmerkung')"
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
import { splitMailsHelper } from "../../../../helpers/EmailHelpers.js"
|
||||
import { splitMailsHelper } from "../../../../helpers/EmailHelpers.js";
|
||||
import { splitMailLinks } from "../../../../helpers/EmailHelpers.js";
|
||||
import FormInput from "../../../Form/Input.js";
|
||||
import FormForm from "../../../Form/Form.js";
|
||||
|
||||
export default {
|
||||
name: "Kontaktieren",
|
||||
components: {
|
||||
FormInput,
|
||||
FormForm
|
||||
},
|
||||
computed: {
|
||||
internMails() {
|
||||
if (this.modelValue.mail_intern)
|
||||
@@ -21,38 +29,150 @@ export default {
|
||||
props: {
|
||||
modelValue: Object
|
||||
},
|
||||
|
||||
inject: {
|
||||
authUid: {
|
||||
from: 'authUid',
|
||||
required: true
|
||||
},
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
mailLinks: [],
|
||||
mailLinksClicked: [],
|
||||
showMailDialog: false,
|
||||
showDivKomp: false,
|
||||
showDivKompLocalStorageId: 'studvw-contact-showDivKomp'
|
||||
}
|
||||
},
|
||||
activated() {
|
||||
const showDivCompLocalStorage = window.localStorage.getItem(this.showDivKompLocalStorageId);
|
||||
this.showDivKomp = (showDivCompLocalStorage === 'true') ? true : false;
|
||||
},
|
||||
methods: {
|
||||
internMail(event) {
|
||||
if (this.internMails.length)
|
||||
{
|
||||
splitMailsHelper(this.internMails, event, null, null, this.$fhcAlert, this.$p)
|
||||
splitMailsHelper(this.internMails, event, null, null, this.$fhcAlert, this.$p, this.authUid)
|
||||
}
|
||||
},
|
||||
privateMail(event) {
|
||||
if (this.privateMails.length)
|
||||
{
|
||||
splitMailsHelper(this.privateMails, event, null,null, this.$fhcAlert, this.$p)
|
||||
splitMailsHelper(this.privateMails, event, null, null, this.$fhcAlert, this.$p, this.authUid)
|
||||
}
|
||||
},
|
||||
createMailLinks(event, mailGroup){
|
||||
let recipients = mailGroup == 'private' ? this.privateMails : this.internMails;
|
||||
this.mailLinks = splitMailLinks(
|
||||
recipients,
|
||||
"",
|
||||
event.ctrlKey || event.metaKey,
|
||||
this.authUid
|
||||
);
|
||||
this.mailLinksClicked = [];
|
||||
|
||||
this.showMailDialog = true;
|
||||
},
|
||||
handleMailLink(link, index){
|
||||
this.mailLinksClicked.push(index);
|
||||
window.open(link, '_blank', 'noopener');
|
||||
},
|
||||
reset(){
|
||||
this.showMailDialog = false;
|
||||
},
|
||||
onSwitchChange(){
|
||||
window.localStorage.setItem(this.showDivKompLocalStorageId, this.showDivKomp);
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
<div id="elementID"></div>
|
||||
<div class="row">
|
||||
<div class="col-lg-2">
|
||||
<button class="btn btn-primary mb-2" @click="internMail($event)" :title="$p.t('stv', 'bccEMail')">
|
||||
<i class="fa-solid fa-mail"></i> {{$p.t('stv', 'internEMail')}}
|
||||
</button>
|
||||
<div class="core-kontaktieren">
|
||||
<div id="elementID"></div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-start pb-3">
|
||||
<a
|
||||
v-if="showMailDialog"
|
||||
class="btn btn-outline-secondary m-2"
|
||||
@click.prevent="reset"
|
||||
>
|
||||
<span class="fa-solid fa-delete-left" :title="this.$p.t('ui','zurueck')" ></span>
|
||||
|
||||
<span>{{ $p.t('ui','zurueck') }}</span>
|
||||
</a>
|
||||
<div v-else> </div>
|
||||
|
||||
<form-input
|
||||
container-class="form-switch mb-0"
|
||||
type="checkbox"
|
||||
:label="$p.t('ui/kompatibilityMode_WebmailClient')"
|
||||
v-model="showDivKomp"
|
||||
@change="onSwitchChange"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
|
||||
<div v-if="!showDivKomp">
|
||||
<div class="row">
|
||||
<div class="col-lg-2">
|
||||
<button class="btn btn-primary mb-2" @click="internMail($event)" :title="$p.t('stv', 'bccEMail')">
|
||||
<i class="fa-solid fa-mail"></i> {{$p.t('stv', 'internEMail')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-2">
|
||||
<button class="btn btn-primary mb-2" @click="privateMail($event)" :title="$p.t('stv', 'bccEMail')">
|
||||
<i class="fa-solid fa-mail"></i> {{$p.t('stv', 'privateEMail')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-2">
|
||||
<button class="btn btn-primary mb-2" @click="privateMail($event)" :title="$p.t('stv', 'bccEMail')">
|
||||
<i class="fa-solid fa-mail"></i> {{$p.t('stv', 'privateEMail')}}
|
||||
</button>
|
||||
|
||||
<div v-if="showDivKomp">
|
||||
|
||||
<div v-if="!showMailDialog" class="row">
|
||||
<div class="col-lg-2">
|
||||
<button class="btn btn-secondary mb-2" @click="createMailLinks($event, 'intern')" :title="$p.t('stv', 'bccEMail')">
|
||||
<i class="fa-solid fa-mail"></i> {{$p.t('stv', 'internEMail')}} ({{$p.t('ui', 'webmailclient')}})
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!showMailDialog" class="row">
|
||||
<div class="col-lg-2">
|
||||
<button class="btn btn-secondary mb-2" @click="createMailLinks($event, 'private')" :title="$p.t('stv', 'bccEMail')">
|
||||
<i class="fa-solid fa-mail"></i> {{$p.t('stv', 'privateEMail')}} ({{$p.t('ui', 'webmailclient')}})
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="showMailDialog" class="mt-3">
|
||||
<div v-if="mailLinks.length > 1" class="mt-2">
|
||||
<p>{{$p.t('stv', 'zuvieleEMails')}}</p>
|
||||
|
||||
<div
|
||||
v-for="(link,index) in mailLinks"
|
||||
:key="index"
|
||||
class="mb-2">
|
||||
<a
|
||||
:href="link"
|
||||
@click.prevent="handleMailLink(link, index)"
|
||||
>
|
||||
Email {{ index + 1 }}
|
||||
</a>
|
||||
<span v-show="mailLinksClicked.includes(index)"> <i class="fa-solid fa-check text-success"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<a
|
||||
:href="mailLinks[0]"
|
||||
@click.prevent="handleMailLink(mailLinks[0], index)"
|
||||
class="btn btn-primary m-2"
|
||||
>
|
||||
{{$p.t('ui', 'openInMailClient')}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>`
|
||||
};
|
||||
</div>
|
||||
`
|
||||
};
|
||||
|
||||
@@ -31,6 +31,11 @@ export default {
|
||||
teacherLoaded: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
gradeListLink() {
|
||||
return this.$api.getUri('/person/gradelist/index/' + this.modelValue.uid);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
reload() {
|
||||
this.$refs.zeugnis.$refs.table.reloadTable();
|
||||
@@ -69,13 +74,21 @@ export default {
|
||||
const savedPath = window.localStorage.getItem(LOCAL_STORAGE_ID);
|
||||
this.stdsem = savedPath || '';
|
||||
},
|
||||
template: `
|
||||
template: /* html */`
|
||||
<div class="stv-details-noten d-flex flex-column overflow-hidden">
|
||||
<div class="mb-3">
|
||||
<select class="form-select" v-model="stdsem" @input="saveStdsem">
|
||||
<option value="">{{ $p.t('ui/current_semester') }}</option>
|
||||
<option value="true">{{ $p.t('ui/all_semester') }}</option>
|
||||
</select>
|
||||
<div class="d-flex justify-content-between my-2">
|
||||
<div>
|
||||
<select class="form-select" v-model="stdsem" @input="saveStdsem">
|
||||
<option value="">{{ $p.t('ui/current_semester') }}</option>
|
||||
<option value="true">{{ $p.t('ui/all_semester') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<a :href="gradeListLink" target="_blank">
|
||||
{{ $p.t('stv/grades_gradelist') }}
|
||||
<i class="fa-solid fa-arrow-up-right-from-square"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
|
||||
@@ -21,6 +21,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
renderTabulator: false,
|
||||
tabulatorEvents: []
|
||||
};
|
||||
},
|
||||
@@ -118,13 +119,13 @@ export default {
|
||||
created() {
|
||||
this.$p.loadCategory(['global', 'stv', 'lehre', 'profil'])
|
||||
.then(() => {
|
||||
if (this.$refs.table.tableBuilt)
|
||||
this.$refs.table.tabulator.columnManager.setColumns(this.tabulatorOptions.columns);
|
||||
this.renderTabulator = true
|
||||
});
|
||||
},
|
||||
template: `
|
||||
<div class="stv-details-noten-repeater d-flex flex-column">
|
||||
<core-filter-cmpt
|
||||
v-if="renderTabulator"
|
||||
ref="table"
|
||||
:title="$p.t('stv/grades_title_repeater')"
|
||||
:tabulator-options="tabulatorOptions"
|
||||
|
||||
@@ -28,11 +28,28 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
renderTabulator: false,
|
||||
setOptinalTabulatorOptionsVisibility: false,
|
||||
tabulatorEvents: [
|
||||
{
|
||||
event: "dataProcessed",
|
||||
handler: () => this.$emit("loaded"),
|
||||
},
|
||||
{
|
||||
event: "tableBuilt",
|
||||
handler: () => {
|
||||
if(this.optionalTabulatorOptions?.visibleColumns
|
||||
&& this.setOptinalTabulatorOptionsVisibility)
|
||||
{
|
||||
for(let key in this.optionalTabulatorOptions.visibleColumns) {
|
||||
if(this.optionalTabulatorOptions.visibleColumns[key])
|
||||
this.$refs.table.tabulator.showColumn(key);
|
||||
else
|
||||
this.$refs.table.tabulator.hideColumn(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
@@ -86,6 +103,8 @@ export default {
|
||||
{ field: 'studiensemester_kurzbz', title: this.$p.t('lehre/studiensemester'), visible: false },
|
||||
{ field: 'note', title: this.$p.t('stv/grades_numericgrade'), visible: false },
|
||||
{ field: 'student_uid', title: this.$p.t('profil/studentIn'), visible: false },
|
||||
{ field: 'vorname', title: this.$p.t('person/vorname'), visible: false },
|
||||
{ field: 'nachname', title: this.$p.t('person/nachname'), visible: false },
|
||||
{ field: 'lehrveranstaltung_id', title: this.$p.t('lehre/lehrveranstaltung_id'), visible: false },
|
||||
{ field: 'punkte', title: this.$p.t('stv/grades_points'), visible: false }
|
||||
],
|
||||
@@ -132,13 +151,19 @@ export default {
|
||||
created() {
|
||||
this.$p.loadCategory(['stv', 'lehre', 'profil'])
|
||||
.then(() => {
|
||||
if (this.$refs.table.tableBuilt)
|
||||
this.$refs.table.tabulator.columnManager.setColumns(this.tabulatorOptions.columns);
|
||||
this.renderTabulator = true;
|
||||
});
|
||||
|
||||
if(this?.optionalTabulatorOptions)
|
||||
{
|
||||
const localStorageKey = 'tabulator-' + this.optionalTabulatorOptions.persistenceTeacherID + '-columns';
|
||||
this.setOptinalTabulatorOptionsVisibility = (window.localStorage.getItem(localStorageKey) === null) ? true : false;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="stv-details-noten-teacher d-flex flex-column">
|
||||
<core-filter-cmpt
|
||||
v-if="renderTabulator"
|
||||
ref="table"
|
||||
:title="$p.t('stv/grades_title_teacher')"
|
||||
:tabulator-options="tabulatorOptions"
|
||||
|
||||
@@ -34,6 +34,8 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
renderTabulator: false,
|
||||
setOptinalTabulatorOptionsVisibility: false,
|
||||
tabulatorEvents: [
|
||||
{
|
||||
event: "dataLoaded",
|
||||
@@ -53,6 +55,21 @@ export default {
|
||||
{
|
||||
event: "rowDeselected",
|
||||
handler: row => row.getElement().style.zIndex = ''
|
||||
},
|
||||
{
|
||||
event: "tableBuilt",
|
||||
handler: () => {
|
||||
if(this.optionalTabulatorOptions?.visibleColumns
|
||||
&& this.setOptinalTabulatorOptionsVisibility)
|
||||
{
|
||||
for(let key in this.optionalTabulatorOptions.visibleColumns) {
|
||||
if(this.optionalTabulatorOptions.visibleColumns[key])
|
||||
this.$refs.table.tabulator.showColumn(key);
|
||||
else
|
||||
this.$refs.table.tabulator.hideColumn(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
stdsem: '',
|
||||
@@ -205,7 +222,10 @@ export default {
|
||||
{ field: 'lehrform', title: this.$p.t('lehre/lehrform'), visible: false },
|
||||
{ field: 'kurzbz', title: this.$p.t('lehre/kurzbz'), visible: false },
|
||||
{ field: 'punkte', title: this.$p.t('stv/grades_points'), visible: false },
|
||||
{ field: 'lehrveranstaltung_bezeichnung_english', title: this.$p.t('stv/grades_lehrveranstaltung_bezeichnung_english'), visible: false }
|
||||
{ field: 'lehrveranstaltung_bezeichnung_english', title: this.$p.t('stv/grades_lehrveranstaltung_bezeichnung_english'), visible: false },
|
||||
{ field: 'uid', title: this.$p.t('person/uid'), visible: false },
|
||||
{ field: 'vorname', title: this.$p.t('person/vorname'), visible: false },
|
||||
{ field: 'nachname', title: this.$p.t('person/nachname'), visible: false }
|
||||
];
|
||||
|
||||
const hasDocuments = ['both', 'inline'].includes(this.config.documents);
|
||||
@@ -215,6 +235,7 @@ export default {
|
||||
columns.push({
|
||||
field: 'actions',
|
||||
title: this.$p.t('global/actions'),
|
||||
minWidth: 120,
|
||||
cssClass: "overflow-visible",
|
||||
headerSort: false,
|
||||
formatter: cell => {
|
||||
@@ -308,13 +329,19 @@ export default {
|
||||
created() {
|
||||
this.$p.loadCategory(['global', 'stv', 'lehre', 'person'])
|
||||
.then(() => {
|
||||
if (this.$refs.table.tableBuilt)
|
||||
this.$refs.table.tabulator.columnManager.setColumns(this.tabulatorOptions.columns);
|
||||
this.renderTabulator = true;
|
||||
});
|
||||
|
||||
if(this?.optionalTabulatorOptions)
|
||||
{
|
||||
const localStorageKey = 'tabulator-' + this.optionalTabulatorOptions.persistenceZeugnisID + '-columns';
|
||||
this.setOptinalTabulatorOptionsVisibility = (window.localStorage.getItem(localStorageKey) === null) ? true : false;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="stv-details-noten-zeugnis h-100 d-flex flex-column">
|
||||
<core-filter-cmpt
|
||||
v-if="renderTabulator"
|
||||
ref="table"
|
||||
:title="$p.t('stv/grades_title_zeugnis')"
|
||||
:tabulator-options="tabulatorOptions"
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
} from "../../../tabulator/filters/extendedHeaderFilter.js";
|
||||
import { addTagInTable, deleteTagInTable, updateTagInTable } from "../../../../js/helpers/TagHelper.js";
|
||||
import { tagFormatter } from "../../../../js/tabulator/formatter/tags.js";
|
||||
import ModalLoading from "./List/ModalLoading.js";
|
||||
|
||||
import ApiTag from "../../../api/factory/stv/tag.js";
|
||||
import ListFilter from './List/Filter.js';
|
||||
@@ -30,7 +31,8 @@ export default {
|
||||
CoreFilterCmpt,
|
||||
ListNew,
|
||||
CoreTag,
|
||||
ListFilter
|
||||
ListFilter,
|
||||
ModalLoading
|
||||
},
|
||||
directives: {
|
||||
draggable
|
||||
@@ -218,10 +220,32 @@ export default {
|
||||
oldScrollUrl: '',
|
||||
oldScrollLeft: 0,
|
||||
oldScrollTop: 0,
|
||||
allPrestudents: []
|
||||
allPrestudents: [],
|
||||
rebuildData: [],
|
||||
isLoading: false,
|
||||
progress: -1,
|
||||
total: -1,
|
||||
processed: -1
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
generalPresets: function() {
|
||||
return [
|
||||
{
|
||||
"id": null,
|
||||
"name": "Standard",
|
||||
"displayedColumns": [
|
||||
"uid","titelpre","tags","nachname","vorname","titelpost",
|
||||
"ersatzkennzeichen","gebdatum","geschlecht",
|
||||
"semester_berechnet","verband","gruppe","studiengang",
|
||||
"matrikelnr","person_id","status","orgform_kurzbz",
|
||||
"studienplan_bezeichnung","prestudent_id","priorisierung_relativ"
|
||||
],
|
||||
"headerFilters": [],
|
||||
"sort": null
|
||||
}
|
||||
];
|
||||
},
|
||||
countsToHTML: function() {
|
||||
return this.$p.t('global/ausgewaehlt')
|
||||
+ ': <strong>' + (this.selectedcount || 0) + '</strong>'
|
||||
@@ -508,7 +532,7 @@ export default {
|
||||
e.preventDefault();
|
||||
|
||||
this.$refs.table.tabulator.deselectRow();
|
||||
this.$refs.table.tabulator.selectRow();
|
||||
this.$refs.table.tabulator.selectRow('active');
|
||||
}
|
||||
|
||||
if (!this.focusObj)
|
||||
@@ -658,6 +682,74 @@ export default {
|
||||
this.oldScrollUrl = this.$refs.table.tabulator.getAjaxUrl();
|
||||
}
|
||||
},
|
||||
async rebuild(selected){
|
||||
const maxbulksize = 25;
|
||||
const minbulksize = 5;
|
||||
let bulksize = minbulksize;
|
||||
this.isLoading = true;
|
||||
let prestudentIds = [];
|
||||
if(!selected.length)
|
||||
prestudentIds = this.$refs.table.tabulator
|
||||
.getData()
|
||||
.map(row => row.prestudent_id);
|
||||
else
|
||||
prestudentIds = selected.map(item => item.prestudent_id);
|
||||
|
||||
this.progress = 0;
|
||||
this.total = prestudentIds.length;
|
||||
this.processed = 0;
|
||||
this.rebuildData = [
|
||||
[],
|
||||
[],
|
||||
[]
|
||||
];
|
||||
|
||||
this.showModal();
|
||||
|
||||
while(this.processed < this.total)
|
||||
{
|
||||
let iteration_prestudentIds = prestudentIds.slice(
|
||||
this.processed,
|
||||
(this.processed + bulksize)
|
||||
);
|
||||
const params = {
|
||||
ids: iteration_prestudentIds,
|
||||
typeId: 'prestudent_id',
|
||||
sem: this.studiensemesterKurzbz
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
const result = await this.$api.call(ApiTag.rebuildTagsforTypeId(params));
|
||||
this.rebuildData[1] = [...this.rebuildData[1], ...result.data[1]];
|
||||
this.rebuildData[2] = [...this.rebuildData[2], ...result.data[2]];
|
||||
}
|
||||
catch(error) {
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
};
|
||||
|
||||
this.processed += iteration_prestudentIds.length;
|
||||
this.progress = Math.round(this.processed * 100 / this.total);
|
||||
|
||||
bulksize = bulksize * 2;
|
||||
if(bulksize > maxbulksize) bulksize = maxbulksize;
|
||||
}
|
||||
|
||||
if(this.rebuildData[1].length > 0)
|
||||
{
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('tag', 'alertSuccessRebuild', { count: this.rebuildData[1].length }));
|
||||
}
|
||||
if(this.rebuildData[2].length > 0)
|
||||
{
|
||||
this.$fhcAlert.alertError(this.$p.t('tag', 'alertErrorRebuild') + this.rebuildData[2].toString());
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
this.$reloadList();
|
||||
},
|
||||
showModal(){
|
||||
this.$refs.modalLocked.open();
|
||||
},
|
||||
},
|
||||
created() {
|
||||
if (this.tagsEnabled) {
|
||||
@@ -690,8 +782,18 @@ export default {
|
||||
// TODO(chris): filter component column chooser has no accessibilty features
|
||||
template: /* html */`
|
||||
<div class="stv-list h-100 pt-3">
|
||||
<modal-loading
|
||||
ref="modalLocked"
|
||||
:isLoading="isLoading"
|
||||
:progress="progress"
|
||||
:total="total"
|
||||
:processed="processed"
|
||||
:message="$p.t('tag','messageModalWait')"
|
||||
>
|
||||
</modal-loading>
|
||||
|
||||
<div
|
||||
class="tabulator-container d-flex flex-column h-100"
|
||||
class="tabulator-container d-flex flex-column h-100 pe-2"
|
||||
:class="{'has-filter': filter.length}"
|
||||
tabindex="0"
|
||||
@focusin="onFocus"
|
||||
@@ -701,6 +803,9 @@ export default {
|
||||
>
|
||||
<core-filter-cmpt
|
||||
ref="table"
|
||||
:isUsingPresets="true"
|
||||
presetsId="studVwListTable"
|
||||
:generalPresets="generalPresets"
|
||||
:description="countsToHTML"
|
||||
:tabulator-options="tabulatorOptions"
|
||||
:tabulator-events="tabulatorEvents"
|
||||
@@ -730,7 +835,7 @@ export default {
|
||||
-->
|
||||
|
||||
<template #additional>
|
||||
<div class="pe-2">
|
||||
<div class="pe-1">
|
||||
<a :href="linkXLS" target="_blank">
|
||||
<i class="fas fa-file-excel fa-xl text-success" :title="$p.t('stv', 'text_exportXLS', { count: selectedPrestudents.length })"></i>
|
||||
</a>
|
||||
@@ -748,6 +853,23 @@ export default {
|
||||
zuordnung_typ="prestudent_id"
|
||||
></core-tag>
|
||||
|
||||
<button
|
||||
v-if="!selected.length"
|
||||
class="btn btn-outline btn-light mb-1"
|
||||
@click="rebuild(selected)"
|
||||
:title="$p.t('tag','rebuild_tags') + ' Stg ' + currentSemester"
|
||||
>
|
||||
<i class="fa-solid fa-refresh pe-1"></i> STG
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
class="btn btn-outline btn-light mb-1"
|
||||
@click="rebuild(selected)"
|
||||
:title="$p.t('tag','rebuild_tags') + ' ' + $p.t('ui','selection') + ' ' + currentSemester"
|
||||
>
|
||||
<i class="fa-solid fa-refresh pe-1"></i> {{selected.length}}
|
||||
</button>
|
||||
|
||||
<template v-if="filter.length || headerFilterActive">
|
||||
<div class="d-flex justify-content-center align-items-center gap-2 ps-4 position-absolute start-50 translate-middle-x">
|
||||
<p class="text-danger mb-0">
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import BsModal from "../../../Bootstrap/Modal.js";
|
||||
import FormForm from "../../../Form/Form.js";
|
||||
|
||||
export default {
|
||||
name: "modalLoading",
|
||||
components: {
|
||||
BsModal,
|
||||
FormForm,
|
||||
PvProgressBar: primevue.progressbar
|
||||
},
|
||||
props: {
|
||||
isLoading: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
message: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
progress: {
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
total: {
|
||||
type: Number,
|
||||
default: -1
|
||||
},
|
||||
processed: {
|
||||
type: Number,
|
||||
default: -1
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return{}
|
||||
},
|
||||
methods:{
|
||||
open(){
|
||||
this.$refs.modalLoading.show();
|
||||
},
|
||||
closeModal(){
|
||||
this.$refs.modalLoading.hide();
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<bs-modal
|
||||
ref="modalLoading"
|
||||
noCloseBtn
|
||||
backdrop='static'
|
||||
:keyboard='false'
|
||||
dialog-class="modal-dialog-scrollable"
|
||||
>
|
||||
<template #title>
|
||||
{{ $p.t('ui/loading') }}
|
||||
</template>
|
||||
|
||||
<form-form
|
||||
ref="formModal"
|
||||
>
|
||||
<div class="mt-3">
|
||||
<div v-if="isLoading">
|
||||
{{message}}
|
||||
</div>
|
||||
<div v-else>
|
||||
{{$p.t('ui', 'fenster_schliessen')}}
|
||||
</div>
|
||||
</div>
|
||||
</form-form>
|
||||
|
||||
<pv-progress-bar v-if="progress >= 0" class="my-3" :value="progress">{{processed}} / {{total}}</pv-progress-bar>
|
||||
|
||||
<template #footer>
|
||||
<div class="d-grid gap-2 d-md-flex justify-content-md-end">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
:disabled="isLoading"
|
||||
@click="closeModal()">
|
||||
{{$p.t('ui', 'schliessen')}}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</bs-modal>
|
||||
`,
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,551 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
import ApiTabulatorPresets from "../../../api/factory/tabulatorPresets.js";
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
export default {
|
||||
name: "TablePresets",
|
||||
props: {
|
||||
presetsId: { type: String },
|
||||
tabulator: { type: Object },
|
||||
generalPresets: { type: Array, default: [] },
|
||||
},
|
||||
emits: ["tablePresetApplied"],
|
||||
data: function () {
|
||||
return {
|
||||
customUserPresets: [],
|
||||
presetInfo: null,
|
||||
newPreset: null,
|
||||
newPresetName: "",
|
||||
presetIndexBeingApplied: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
allPresets() {
|
||||
return this.$props.generalPresets.concat(this.customUserPresets);
|
||||
},
|
||||
presetInfoFormattedStrings() {
|
||||
if (!this.presetInfo) return null;
|
||||
|
||||
const columnTitles = this.getColumnTitles();
|
||||
|
||||
let displayedColumns =
|
||||
this.presetInfo.displayedColumns?.map(
|
||||
(columnField) => columnTitles[columnField] ?? "",
|
||||
) ?? [];
|
||||
displayedColumns = displayedColumns.filter(
|
||||
(string) => string.length,
|
||||
);
|
||||
const displayedColumnsString = displayedColumns.length
|
||||
? this.$p.t("tabulator_presets/displayed_columns") +
|
||||
" (" +
|
||||
this.$p.t("tabulator_presets/in_order") +
|
||||
"): " +
|
||||
displayedColumns.join(", ")
|
||||
: "";
|
||||
|
||||
let headerFilters = this.presetInfo.headerFilters
|
||||
? Object.keys(this.presetInfo.headerFilters).map((column) =>
|
||||
columnTitles[column]
|
||||
? columnTitles[column] +
|
||||
'["' +
|
||||
this.presetInfo.headerFilters[column] +
|
||||
'"]'
|
||||
: "",
|
||||
)
|
||||
: [];
|
||||
headerFilters = headerFilters.filter((string) => string.length);
|
||||
const headerFiltersString = headerFilters.length
|
||||
? this.$p.t("tabulator_presets/column_header_filters") +
|
||||
": " +
|
||||
headerFilters.join(", ")
|
||||
: "";
|
||||
|
||||
const sortColumn = this.presetInfo.sort?.column
|
||||
? columnTitles[this.presetInfo.sort.column]
|
||||
: null;
|
||||
const sortDirection =
|
||||
this.presetInfo.sort?.direction === "desc"
|
||||
? this.$p.t("tabulator_presets/desc")
|
||||
: this.$p.t("tabulator_presets/asc");
|
||||
const sortString = sortColumn
|
||||
? this.$p.t("tabulator_presets/sort") +
|
||||
": " +
|
||||
sortColumn +
|
||||
" (" +
|
||||
sortDirection +
|
||||
")"
|
||||
: "";
|
||||
|
||||
return {
|
||||
displayedColumns: displayedColumnsString,
|
||||
headerFilters: headerFiltersString,
|
||||
sort: sortString,
|
||||
};
|
||||
},
|
||||
newPresetFormattedStrings() {
|
||||
if (!this.newPreset) return null;
|
||||
|
||||
const columnTitles = this.getColumnTitles();
|
||||
|
||||
const displayedColumns = this.newPreset.displayedColumns.map(
|
||||
(columnField) => columnTitles[columnField],
|
||||
);
|
||||
const displayedColumnsString = displayedColumns.length
|
||||
? this.$p.t("tabulator_presets/displayed_columns") +
|
||||
" (" +
|
||||
this.$p.t("tabulator_presets/in_order") +
|
||||
"): " +
|
||||
displayedColumns.join(", ")
|
||||
: "";
|
||||
|
||||
const headerFilters = Object.keys(this.newPreset.headerFilters).map(
|
||||
(column) =>
|
||||
columnTitles[column] +
|
||||
'["' +
|
||||
this.newPreset.headerFilters[column] +
|
||||
'"]',
|
||||
);
|
||||
const headerFiltersString = headerFilters.length
|
||||
? this.$p.t("tabulator_presets/column_header_filters") +
|
||||
": " +
|
||||
headerFilters.join(", ")
|
||||
: "";
|
||||
|
||||
const sortColumn = this.newPreset.sort?.column
|
||||
? columnTitles[this.newPreset.sort.column]
|
||||
: null;
|
||||
const sortDirection =
|
||||
this.newPreset.sort?.direction === "desc"
|
||||
? this.$p.t("tabulator_presets/desc")
|
||||
: this.$p.t("tabulator_presets/asc");
|
||||
const sortString = sortColumn
|
||||
? this.$p.t("tabulator_presets/sort") +
|
||||
": " +
|
||||
sortColumn +
|
||||
" (" +
|
||||
sortDirection +
|
||||
")"
|
||||
: "";
|
||||
|
||||
return {
|
||||
displayedColumns: displayedColumnsString,
|
||||
headerFilters: headerFiltersString,
|
||||
sort: sortString,
|
||||
};
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
allPresets: {
|
||||
handler() {
|
||||
this.hidePresetInfo();
|
||||
this.hideNewPresetForm();
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getPresetIndex() {
|
||||
return this.presetIndexBeingApplied;
|
||||
},
|
||||
async showPresetInfo(preset) {
|
||||
let shouldUpdatePresetInfo;
|
||||
if (!this.presetInfo) {
|
||||
shouldUpdatePresetInfo = true;
|
||||
} else if (preset.id) {
|
||||
shouldUpdatePresetInfo = preset.id !== this.presetInfo.id;
|
||||
} else {
|
||||
shouldUpdatePresetInfo = preset.name !== this.presetInfo.name;
|
||||
}
|
||||
|
||||
if (shouldUpdatePresetInfo) {
|
||||
this.presetInfo = { ...preset };
|
||||
}
|
||||
|
||||
this.hideNewPresetForm();
|
||||
|
||||
await this.$nextTick();
|
||||
|
||||
if (
|
||||
!this.$refs.presetInfoCollapsible
|
||||
.getAttribute("class")
|
||||
.split(" ")
|
||||
.includes("show")
|
||||
) {
|
||||
this.togglePresetInfoCollapsible();
|
||||
}
|
||||
},
|
||||
async hidePresetInfo() {
|
||||
if (
|
||||
this.$refs.presetInfoCollapsible
|
||||
.getAttribute("class")
|
||||
.split(" ")
|
||||
.includes("show")
|
||||
) {
|
||||
this.togglePresetInfoCollapsible();
|
||||
}
|
||||
await this.$nextTick();
|
||||
this.presetInfo = null;
|
||||
},
|
||||
togglePresetInfoCollapsible() {
|
||||
new bootstrap.Collapse(
|
||||
"#presetInfoCollapsible_" + this.$props.presetsId,
|
||||
{ toggle: true },
|
||||
);
|
||||
},
|
||||
async showNewPresetForm() {
|
||||
this.generateNewPreset();
|
||||
|
||||
this.hidePresetInfo();
|
||||
|
||||
await this.$nextTick();
|
||||
|
||||
if (
|
||||
!this.$refs.newPresetFormCollapsible
|
||||
.getAttribute("class")
|
||||
.split(" ")
|
||||
.includes("show")
|
||||
) {
|
||||
this.toggleNewPresetFormCollapsible();
|
||||
}
|
||||
},
|
||||
generateNewPreset() {
|
||||
const columns = this.tabulator.columnManager.columns.filter(
|
||||
(column) => column.field !== "collapse",
|
||||
);
|
||||
|
||||
const displayedColumns = columns
|
||||
.filter((column) => column.visible)
|
||||
.map((column) => column.field);
|
||||
|
||||
const unparsedHeaderFilters =
|
||||
this.tabulator.modules.filter.headerFilters;
|
||||
const headerFilterFieldValuePairs = Object.entries(
|
||||
unparsedHeaderFilters,
|
||||
).map(([columnField, filter]) => [columnField, filter.value]);
|
||||
const headerFiltersFieldValuePairsExcludingHiddenColumns =
|
||||
headerFilterFieldValuePairs.filter(
|
||||
([columnField, filterValue]) => {
|
||||
return displayedColumns.includes(columnField);
|
||||
},
|
||||
);
|
||||
const headerFilters = Object.fromEntries(
|
||||
headerFiltersFieldValuePairsExcludingHiddenColumns,
|
||||
);
|
||||
|
||||
const activeSort = this.tabulator.getSorters()[0];
|
||||
const sort = activeSort
|
||||
? {
|
||||
column: activeSort.field,
|
||||
direction: activeSort.dir,
|
||||
}
|
||||
: null;
|
||||
|
||||
this.newPreset = {
|
||||
displayedColumns,
|
||||
headerFilters,
|
||||
sort,
|
||||
};
|
||||
},
|
||||
hideNewPresetForm() {
|
||||
if (
|
||||
this.$refs.newPresetFormCollapsible
|
||||
.getAttribute("class")
|
||||
.split(" ")
|
||||
.includes("show")
|
||||
) {
|
||||
this.toggleNewPresetFormCollapsible();
|
||||
}
|
||||
},
|
||||
toggleNewPresetFormCollapsible() {
|
||||
this.newPresetName = "";
|
||||
new bootstrap.Collapse(
|
||||
"#newPresetFormCollapsible_" + this.$props.presetsId,
|
||||
{ toggle: true },
|
||||
);
|
||||
},
|
||||
async createPreset() {
|
||||
if (!this.newPresetName?.length) return;
|
||||
|
||||
const presetCreationResponse = await this.$api.call(
|
||||
ApiTabulatorPresets.createTabulatorPreset(
|
||||
this.$props.presetsId,
|
||||
this.newPresetName,
|
||||
this.newPreset,
|
||||
),
|
||||
);
|
||||
|
||||
if (presetCreationResponse.meta.status === "success") {
|
||||
this.fetchCustomUserTabulatorPresets();
|
||||
this.hideNewPresetForm();
|
||||
}
|
||||
},
|
||||
async deletePreset(preset) {
|
||||
if (!preset.id) return;
|
||||
|
||||
if (
|
||||
window.confirm(
|
||||
this.$p
|
||||
.t("tabulator_presets/preset_deletion_confirmation")
|
||||
.replace("(((presetName)))", preset.name),
|
||||
)
|
||||
) {
|
||||
const presetDeletionResponse = await this.$api.call(
|
||||
ApiTabulatorPresets.deleteTabulatorPreset(preset.id),
|
||||
);
|
||||
|
||||
if (presetDeletionResponse.meta.status === "success") {
|
||||
this.fetchCustomUserTabulatorPresets();
|
||||
}
|
||||
}
|
||||
},
|
||||
syncPresetWithConfig(preset) {
|
||||
const validColumns = this.$props.tabulator.getColumnDefinitions();
|
||||
let isUpdateNecessary = false;
|
||||
|
||||
if (preset.displayedColumns) {
|
||||
const initialNumberOfDisplayedColumns =
|
||||
preset.displayedColumns.length;
|
||||
preset.displayedColumns = preset.displayedColumns.filter(
|
||||
(columnField) => {
|
||||
return validColumns.some(
|
||||
(column) => column.field === columnField,
|
||||
);
|
||||
},
|
||||
);
|
||||
const updatedNumberOfDisplayedColumns =
|
||||
preset.displayedColumns.length;
|
||||
|
||||
isUpdateNecessary =
|
||||
updatedNumberOfDisplayedColumns <
|
||||
initialNumberOfDisplayedColumns;
|
||||
}
|
||||
|
||||
if (preset.headerFilters) {
|
||||
const initialNumberOfHeaderFilters = Object.keys(
|
||||
preset.headerFilters,
|
||||
).length;
|
||||
Object.keys(preset.headerFilters).forEach((columnField) => {
|
||||
if (
|
||||
!validColumns.some(
|
||||
(column) =>
|
||||
column.field === columnField &&
|
||||
column.headerFilter,
|
||||
) ||
|
||||
!preset.displayedColumns.includes(columnField)
|
||||
) {
|
||||
delete preset.headerFilters[columnField];
|
||||
}
|
||||
});
|
||||
const updatedNumberOfHeaderFilters = Object.keys(
|
||||
preset.headerFilters,
|
||||
).length;
|
||||
|
||||
isUpdateNecessary =
|
||||
isUpdateNecessary ||
|
||||
updatedNumberOfHeaderFilters < initialNumberOfHeaderFilters;
|
||||
}
|
||||
|
||||
if (preset.sort) {
|
||||
if (
|
||||
!validColumns.some(
|
||||
(column) =>
|
||||
column.field === preset.sort.column &&
|
||||
column.headerSort,
|
||||
)
|
||||
) {
|
||||
preset.sort = null;
|
||||
isUpdateNecessary = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isUpdateNecessary) {
|
||||
this.updatePreset(preset);
|
||||
}
|
||||
|
||||
return preset;
|
||||
},
|
||||
async updatePreset(preset) {
|
||||
if (!preset.id) return;
|
||||
|
||||
const tabulatorPresetUpdateResponse = await this.$api.call(
|
||||
ApiTabulatorPresets.updateTabulatorPreset(preset.id, {
|
||||
displayedColumns: preset.displayedColumns,
|
||||
headerFilters: preset.headerFilters,
|
||||
sort: preset.sort,
|
||||
}),
|
||||
);
|
||||
|
||||
if (tabulatorPresetUpdateResponse.meta.status === "success") {
|
||||
this.fetchCustomUserTabulatorPresets();
|
||||
}
|
||||
},
|
||||
async applyPreset(preset, index) {
|
||||
this.presetIndexBeingApplied = index;
|
||||
|
||||
// workaround for updating DOM and displaying preset-loading spinner
|
||||
// conventional use of $nextTick ineffective
|
||||
setTimeout(() => {
|
||||
preset = this.syncPresetWithConfig(preset);
|
||||
window.localStorage["tabulatorPreset-" + this.$props.presetsId] =
|
||||
preset.id ? "custom:" + preset.id : "general:" + preset.name;
|
||||
|
||||
this.$props.tabulator.modules.tablePresets.applyPreset(preset);
|
||||
|
||||
this.$emit("tablePresetApplied", { preset });
|
||||
|
||||
this.presetIndexBeingApplied = null;
|
||||
}, 50);
|
||||
},
|
||||
async fetchCustomUserTabulatorPresets() {
|
||||
let tabulatorPresetsResponse = await this.$api.call(
|
||||
ApiTabulatorPresets.getTabulatorPresets(this.$props.presetsId),
|
||||
);
|
||||
|
||||
if (tabulatorPresetsResponse.meta.status === "success") {
|
||||
this.customUserPresets = tabulatorPresetsResponse.data.map(
|
||||
(presetInfo) => {
|
||||
return {
|
||||
id: presetInfo.preset_id,
|
||||
name: presetInfo.preset_name,
|
||||
...JSON.parse(presetInfo.preset_json),
|
||||
};
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
getColumnTitles() {
|
||||
const columnLocalizations =
|
||||
this.$props.tabulator.getLocale() !== "default"
|
||||
? this.$props.tabulator.getLang().columns
|
||||
: {};
|
||||
const columnFieldTitlePairs = this.$props.tabulator
|
||||
.getColumnDefinitions()
|
||||
.map((column) => [
|
||||
column.field,
|
||||
columnLocalizations[column.field] ?? column.title,
|
||||
]);
|
||||
return Object.fromEntries(columnFieldTitlePairs);
|
||||
},
|
||||
applyStoredPreset() {
|
||||
let storedPreset =
|
||||
window.localStorage["tabulatorPreset-" + this.$props.presetsId];
|
||||
if (!storedPreset) return;
|
||||
|
||||
let preset = null;
|
||||
|
||||
if (storedPreset.search("custom:") === 0) {
|
||||
const customPresetId = parseInt(storedPreset.slice(7));
|
||||
preset = this.customUserPresets.find(
|
||||
(customPreset) => customPreset.id === customPresetId,
|
||||
);
|
||||
} else if (storedPreset.search("general:") === 0) {
|
||||
const generalPresetName = storedPreset.slice(8);
|
||||
preset = this.$props.generalPresets.find(
|
||||
(generalPreset) => generalPreset.name === generalPresetName,
|
||||
);
|
||||
}
|
||||
|
||||
if (!preset) return;
|
||||
|
||||
this.applyPreset(preset, null);
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
await this.$p.loadCategory(["tabulator_presets", "global"]);
|
||||
await this.fetchCustomUserTabulatorPresets();
|
||||
this.applyStoredPreset();
|
||||
},
|
||||
template: /*html*/ `
|
||||
<div>
|
||||
<div class="card">
|
||||
<div class="card-header">{{ $p.t("tabulator_presets/table_presets") }}</div>
|
||||
<div class="card-body d-flex flex-column">
|
||||
<div class="d-flex flex-row gap-1 justify-content-start flex-wrap">
|
||||
<div v-for="(preset, index) in allPresets" class="d-flex flex-column gap-1 mb-2">
|
||||
<div @click="applyPreset(preset, index)" class="position-relative btn btn-dark py-1 px-2">
|
||||
<span :class="{'opacity-0': getPresetIndex() === index}">{{ preset.name }}</span>
|
||||
<div
|
||||
v-if="getPresetIndex() === index"
|
||||
class="position-absolute d-flex flex-row align-items-center justify-content-center"
|
||||
style="inset:0;"
|
||||
>
|
||||
<div class="spinner-border spinner-border-sm" role="status" style>
|
||||
<span class="visually-hidden">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-row justify-content-center">
|
||||
<div class="d-flex flex-row gap-2 px-3">
|
||||
<span @click="showPresetInfo(preset)" type="button" class="fa-solid fa-circle-info"></span>
|
||||
<span v-if="preset.id" @click="deletePreset(preset)" type="button" class="fa-solid fa-trash-can"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div @click="showNewPresetForm()" class="btn btn-dark py-1 px-2 d-flex flex-row align-items-center gap-1">
|
||||
<span class="fa-solid fa-plus"></span>
|
||||
<span class="flex-nowrap">{{ $p.t("tabulator_presets/save_current_config") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :id="'presetInfoCollapsible_' + $props.presetsId" ref="presetInfoCollapsible" class="collapse">
|
||||
<div class="d-flex flex-column">
|
||||
<hr />
|
||||
<div class="d-flex flex-column gap-2">
|
||||
<div class="w-100 d-flex flex-row justify-content-between">
|
||||
<span class="fw-bold">{{ presetInfo?.name }}</span>
|
||||
<span @click="hidePresetInfo()" type="button" class="fa-solid fa-xmark"></span>
|
||||
</div>
|
||||
<span v-if="presetInfoFormattedStrings?.displayedColumns.length">{{ presetInfoFormattedStrings.displayedColumns }}</span>
|
||||
<span v-if="presetInfoFormattedStrings?.headerFilters.length">{{ presetInfoFormattedStrings.headerFilters }}</span>
|
||||
<span v-if="presetInfoFormattedStrings?.sort.length">{{ presetInfoFormattedStrings.sort }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :id="'newPresetFormCollapsible_' + $props.presetsId" ref="newPresetFormCollapsible" class="collapse">
|
||||
<div class="d-flex flex-column">
|
||||
<hr />
|
||||
<div class="d-flex flex-column gap-2">
|
||||
<div class="w-100 d-flex flex-row justify-content-between">
|
||||
<span class="fw-bold">{{ $p.t("tabulator_presets/save_current_config") }}</span>
|
||||
<span @click="hideNewPresetForm()" type="button" class="fa-solid fa-xmark"></span>
|
||||
</div>
|
||||
<span v-if="newPresetFormattedStrings?.displayedColumns.length">{{ newPresetFormattedStrings.displayedColumns }}</span>
|
||||
<span v-if="newPresetFormattedStrings?.headerFilters.length">{{ newPresetFormattedStrings.headerFilters }}</span>
|
||||
<span v-if="newPresetFormattedStrings?.sort.length">{{ newPresetFormattedStrings.sort }}</span>
|
||||
<div class="d-flex flex-row justify-content-center align-items-center gap-2">
|
||||
<input v-model="newPresetName" :placeholder="$p.t('tabulator_presets/preset_name')" />
|
||||
<div
|
||||
@click="createPreset()"
|
||||
:class="{'opacity-50 pe-none': !newPresetName?.length}"
|
||||
class="btn btn-dark py-1 px-2"
|
||||
>
|
||||
{{ $p.t('global/speichern') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
export async function splitMailsHelper(mails, event, subject, body, alertPluginRef, phrasenPluginRef) {
|
||||
export async function splitMailsHelper(mails, event, subject, body, alertPluginRef, phrasenPluginRef, uidCC) {
|
||||
await phrasenPluginRef.loadCategory('ui');
|
||||
|
||||
let splititem = ",";
|
||||
let maillist = mails.join(splititem);
|
||||
let useBcc = event?.ctrlKey || event?.metaKey;
|
||||
@@ -46,7 +47,10 @@ export async function splitMailsHelper(mails, event, subject, body, alertPluginR
|
||||
}
|
||||
|
||||
// construct the clean mailLink
|
||||
let mailLink = useBcc ? `mailto:?bcc=${mailto}` : `mailto:${mailto}`;
|
||||
let mailadressUid = (uidCC && typeof uidCC === 'string')
|
||||
? uidCC + '@' + FHC_JS_DATA_STORAGE_OBJECT.domain
|
||||
: 'noreply@' + FHC_JS_DATA_STORAGE_OBJECT.domain;
|
||||
let mailLink = useBcc ? `mailto:${mailadressUid}?cc=${mailadressUid}&bcc=${mailto}` : `mailto:${mailto}`;
|
||||
if (queryString) {
|
||||
// If using BCC, the string already has a '?', so append with '&'. Otherwise, start with '?'
|
||||
mailLink += useBcc ? `&${queryString}` : `?${queryString}`;
|
||||
@@ -63,4 +67,79 @@ export async function splitMailsHelper(mails, event, subject, body, alertPluginR
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* just splits the list of mails
|
||||
*
|
||||
* @param mails emailadresses
|
||||
* @param subject subject
|
||||
* @param useBcc useBcc
|
||||
* @returns array of links for splitted mails
|
||||
*/
|
||||
export function splitMailLinks(mails, subject = "", useBcc = false, uidCC= "", maxLength = 2024) {
|
||||
if (!Array.isArray(mails) || mails.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const separator = ",";
|
||||
const encodedSubject = subject ? encodeURIComponent(subject) : "";
|
||||
|
||||
// reserve space for the subject parameter
|
||||
const subjectLength = encodedSubject
|
||||
? `?subject=${encodedSubject}`.length
|
||||
: 0;
|
||||
|
||||
const limit = maxLength - subjectLength;
|
||||
|
||||
const links = [];
|
||||
let currentRecipients = [];
|
||||
|
||||
for (const mail of mails) {
|
||||
if (!mail) continue;
|
||||
|
||||
const testRecipients = [...currentRecipients, mail];
|
||||
const recipientString = testRecipients.join(separator);
|
||||
|
||||
if (recipientString.length > limit && currentRecipients.length > 0) {
|
||||
|
||||
links.push(createMailto(
|
||||
currentRecipients.join(separator),
|
||||
encodedSubject,
|
||||
useBcc,
|
||||
uidCC
|
||||
));
|
||||
|
||||
currentRecipients = [mail];
|
||||
}
|
||||
else {
|
||||
currentRecipients.push(mail);
|
||||
}
|
||||
}
|
||||
|
||||
if (currentRecipients.length > 0) {
|
||||
links.push(createMailto(
|
||||
currentRecipients.join(separator),
|
||||
encodedSubject,
|
||||
useBcc,
|
||||
uidCC
|
||||
));
|
||||
}
|
||||
|
||||
return links;
|
||||
}
|
||||
|
||||
function createMailto(recipients, encodedSubject, useBcc, uidCC) {
|
||||
let mailadressUid = uidCC + '@technikum-wien.at';
|
||||
|
||||
let link = useBcc
|
||||
? `mailto:${encodeURIComponent(mailadressUid)}?cc=${encodeURIComponent(mailadressUid)}&bcc=${encodeURIComponent(recipients)}`
|
||||
: `mailto:${encodeURIComponent(recipients)}`;
|
||||
|
||||
if (encodedSubject) {
|
||||
link += `${useBcc ? "&" : "?"}subject=${encodedSubject}`;
|
||||
}
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
@@ -6,18 +6,9 @@ export function addTagInTable(addedTag, rows, matchKey, tagsKey = "tags")
|
||||
rows.forEach(row =>
|
||||
{
|
||||
const rowData = row.getData();
|
||||
|
||||
//add save check if String or Array and avoid same reference later for mutations
|
||||
let raw = rowData[tagsKey];
|
||||
let tags = typeof raw === "string"
|
||||
? JSON.parse(raw || "[]")
|
||||
: Array.isArray(raw)
|
||||
? [...raw]
|
||||
: [];
|
||||
|
||||
let updated = false;
|
||||
|
||||
for (const tag of addedTag.response)
|
||||
addedTag.response.forEach(tag =>
|
||||
{
|
||||
if (rowData[matchKey] !== tag[matchKey])
|
||||
return;
|
||||
@@ -52,16 +43,10 @@ export function addTagInTable(addedTag, rows, matchKey, tagsKey = "tags")
|
||||
});
|
||||
rowData[tagsKey] = JSON.stringify(tags);
|
||||
updated = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (updated)
|
||||
{
|
||||
row.update({
|
||||
[tagsKey]: JSON.stringify(tags)
|
||||
});
|
||||
|
||||
row.reformat();
|
||||
}
|
||||
row.update(rowData);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -75,10 +60,8 @@ export function deleteTagInTable(deletedTag, rows, tagsKeys = ['tags'])
|
||||
let updates = {};
|
||||
let changed = false;
|
||||
|
||||
for (const key of tagsKeys) {
|
||||
let raw = rowData[key];
|
||||
|
||||
let tags = [];
|
||||
tagsKeys.forEach(key => {
|
||||
let tags;
|
||||
|
||||
try {
|
||||
let initialTags = rowData[key] || "[]";
|
||||
@@ -92,15 +75,15 @@ export function deleteTagInTable(deletedTag, rows, tagsKeys = ['tags'])
|
||||
}
|
||||
|
||||
if (!Array.isArray(tags))
|
||||
continue;
|
||||
return;
|
||||
|
||||
let filtered = tags.filter(tag => tag?.id !== deletedTag);
|
||||
|
||||
if (filtered.length !== tags.length) {
|
||||
if (filtered.length !== tags.length)
|
||||
{
|
||||
updates[key] = JSON.stringify(filtered);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (changed) {
|
||||
row.update(updates);
|
||||
@@ -109,6 +92,7 @@ export function deleteTagInTable(deletedTag, rows, tagsKeys = ['tags'])
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function updateTagInTable(updatedTag, rows, fields = ['tags'])
|
||||
{
|
||||
if (!Array.isArray(fields))
|
||||
|
||||
@@ -9,9 +9,13 @@ export default class ResponsiveLayoutExtensionModule extends ResponsiveLayout {
|
||||
}
|
||||
|
||||
generateCollapsedRowData(row) {
|
||||
let result = super.generateCollapsedRowData(row)
|
||||
const isLocalizationEnabled = this.table.options.locale && this.table.options.locale !== "default";
|
||||
const columnHeadingTranslations = this.table?.getLang()?.columns;
|
||||
let result = super.generateCollapsedRowData(row);
|
||||
const isLocalizationEnabled =
|
||||
this.table.options.locale &&
|
||||
this.table.options.locale !== "default";
|
||||
const columnHeadingTranslations = this.table?.initialized
|
||||
? this.table.getLang()?.columns
|
||||
: null;
|
||||
|
||||
if (isLocalizationEnabled && columnHeadingTranslations) {
|
||||
result = result.map((column) => {
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import Module from "../../../../vendor/olifolkerd/tabulator5/src/js/core/Module.js";
|
||||
|
||||
export default class TablePresetsModule extends Module {
|
||||
static moduleName = "tablePresets";
|
||||
static moduleInitNumber = 1;
|
||||
|
||||
constructor(table) {
|
||||
super(table);
|
||||
}
|
||||
|
||||
applyPreset(preset) {
|
||||
let columnsConfig = this.table.options.columns;
|
||||
let reorderedColumnsConfig = [];
|
||||
preset.displayedColumns.forEach((columnField) => {
|
||||
let columnConfig = columnsConfig.find(
|
||||
(column) => column.field === columnField,
|
||||
);
|
||||
if (!columnConfig) return;
|
||||
columnConfig.visible = true;
|
||||
reorderedColumnsConfig.push(columnConfig);
|
||||
});
|
||||
|
||||
let hiddenColumnsConfig = columnsConfig
|
||||
.filter((column) => !preset.displayedColumns.includes(column.field))
|
||||
.map((column) => {
|
||||
column.visible = false;
|
||||
return column;
|
||||
});
|
||||
this.table.setColumns(
|
||||
reorderedColumnsConfig.concat(hiddenColumnsConfig),
|
||||
);
|
||||
|
||||
this.table.clearHeaderFilter();
|
||||
if (preset.headerFilters) {
|
||||
Object.entries(preset.headerFilters).forEach(
|
||||
([columnField, filterValue]) => {
|
||||
this.table.setHeaderFilterValue(columnField, filterValue);
|
||||
|
||||
// double checking if filter inputs are filled in due to issues with custom header filters
|
||||
const headerFilterInputElement =
|
||||
this.table.columnManager.columns
|
||||
.find((column) => column.field === columnField)
|
||||
?.element.querySelector(
|
||||
".tabulator-header-filter input",
|
||||
);
|
||||
if (
|
||||
headerFilterInputElement &&
|
||||
headerFilterInputElement.value !== filterValue
|
||||
) {
|
||||
headerFilterInputElement.value = filterValue;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
this.table.clearSort();
|
||||
if (preset.sort?.column) {
|
||||
this.table.setSort(
|
||||
preset.sort.column,
|
||||
preset.sort.direction ?? "asc",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -99,6 +99,7 @@ require_once('dbupdate_3.4/68957_dashboard_bookmark_neue_Spalte_sort.php');
|
||||
require_once('dbupdate_3.4/68530_Dashboard_Cleanup.php');
|
||||
require_once('dbupdate_3.4/75959_StudVw_Automatische_Tags.php');
|
||||
require_once('dbupdate_3.4/76160_lvv_favorites.php');
|
||||
require_once('dbupdate_3.4/77080_tabulator_presets_table.php');
|
||||
|
||||
// *** Pruefung und hinzufuegen der neuen Attribute und Tabellen
|
||||
echo '<H2>Pruefe Tabellen und Attribute!</H2>';
|
||||
@@ -396,6 +397,7 @@ $tabellen=array(
|
||||
"public.tbl_studiengangstyp" => array("typ","bezeichnung","beschreibung","bezeichnung_mehrsprachig"),
|
||||
"public.tbl_studienjahr" => array("studienjahr_kurzbz","bezeichnung"),
|
||||
"public.tbl_studiensemester" => array("studiensemester_kurzbz","bezeichnung","start","ende","studienjahr_kurzbz","ext_id","beschreibung","onlinebewerbung"),
|
||||
"public.tbl_tabulator_presets" => array("preset_id", "benutzer_uid", "table_name", "preset_json"),
|
||||
"public.tbl_tag" => array("tag"),
|
||||
"public.tbl_variable" => array("name","uid","wert"),
|
||||
"public.tbl_variablenname" => array("name","defaultwert"),
|
||||
|
||||
@@ -16,7 +16,7 @@ if(!@$db->db_query("SELECT taglib FROM public.tbl_notiz_typ LIMIT 1"))
|
||||
$tags = [
|
||||
[
|
||||
'typ_kurzbz' => 'wh_auto',
|
||||
'bezeichnung' => '{WH, R}',
|
||||
'bezeichnung' => '{WH, WH}',
|
||||
'style' => 'tag_dark_grey',
|
||||
'prioritaet' => 11,
|
||||
'taglib' => 'tags/CoreWiederholerTagLib'
|
||||
@@ -30,14 +30,14 @@ $tags = [
|
||||
],
|
||||
[
|
||||
'typ_kurzbz' => 'out_auto',
|
||||
'bezeichnung' => '{Out, Out}',
|
||||
'bezeichnung' => '{Outgoing, Outgoing}',
|
||||
'style' => 'tag_limette',
|
||||
'prioritaet' => 12,
|
||||
'taglib' => 'tags/CoreOutgoingTagLib'
|
||||
],
|
||||
[
|
||||
'typ_kurzbz' => 'prewh_auto',
|
||||
'bezeichnung' => '{Pre-WH, pre-R}',
|
||||
'bezeichnung' => '{Pre-WH, pre-WH}',
|
||||
'style' => 'tag_light_grey',
|
||||
'prioritaet' => 13,
|
||||
'taglib' => 'tags/CorePrewiederholerTagLib'
|
||||
@@ -51,7 +51,7 @@ $tags = [
|
||||
],
|
||||
[
|
||||
'typ_kurzbz' => 'unterbrecher_auto',
|
||||
'bezeichnung' => '{UB, I}',
|
||||
'bezeichnung' => '{UB, UB}',
|
||||
'style' => 'tag_turquoise',
|
||||
'prioritaet' => 15,
|
||||
'taglib' => 'tags/CoreUnterbrecherTagLib'
|
||||
@@ -70,6 +70,20 @@ $tags = [
|
||||
'prioritaet' => 17,
|
||||
'taglib' => 'tags/CoreJgvTagLib'
|
||||
],
|
||||
[
|
||||
'typ_kurzbz' => 'preabbr_auto',
|
||||
'bezeichnung' => '{Pre-Abbr, pre-Abbr}',
|
||||
'style' => 'tag_blush',
|
||||
'prioritaet' => 18,
|
||||
'taglib' => 'tags/CorePreabbrecherTagLib'
|
||||
],
|
||||
[
|
||||
'typ_kurzbz' => 'in_auto',
|
||||
'bezeichnung' => '{Incoming, Incoming}',
|
||||
'style' => 'tag_skyblue',
|
||||
'prioritaet' => 19,
|
||||
'taglib' => 'tags/CoreIncomingTagLib'
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
if (!defined('DB_NAME'))
|
||||
exit('No direct script access allowed');
|
||||
|
||||
if (!$result = @$db->db_query("SELECT 1 FROM public.tbl_tabulator_presets LIMIT 1")) {
|
||||
$qry = "CREATE TABLE public.tbl_tabulator_presets (
|
||||
preset_id int NOT NULL,
|
||||
benutzer_uid varchar(33) NOT NULL,
|
||||
table_name varchar(255) NOT NULL,
|
||||
preset_name varchar(255) NOT NULL,
|
||||
preset_json varchar(10000) NOT NULL,
|
||||
CONSTRAINT tbl_tabulator_presets_preset_id_pk PRIMARY KEY(preset_id),
|
||||
CONSTRAINT tbl_tabulator_presets_benutzer_uid_fk FOREIGN KEY (benutzer_uid) REFERENCES public.tbl_benutzer(uid)
|
||||
);";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>public.tbl_tabulator_presets: ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo '<br>public.tbl_tabulator_presets: table created';
|
||||
|
||||
|
||||
$db->db_query('CREATE SEQUENCE IF NOT EXISTS public.seq_tbl_tabulator_presets_preset_id
|
||||
INCREMENT BY 1
|
||||
NO MAXVALUE
|
||||
NO MINVALUE
|
||||
CACHE 1;');
|
||||
|
||||
$db->db_query("ALTER TABLE public.tbl_tabulator_presets ALTER COLUMN preset_id SET DEFAULT nextval('public.seq_tbl_tabulator_presets_preset_id');");
|
||||
|
||||
|
||||
$qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE public.tbl_tabulator_presets TO web;';
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>public.tbl_tabulator_presets: ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>web</strong> on public.tbl_tabulator_presets';
|
||||
|
||||
$qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE public.tbl_tabulator_presets TO vilesci;';
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>public.tbl_tabulator_presets: ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>vilesci</strong> on public.tbl_tabulator_presets';
|
||||
|
||||
$qry = 'GRANT USAGE ON public.seq_tbl_tabulator_presets_preset_id TO web;';
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>public.tbl_tabulator_presets: ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>web</strong> on public.tbl_tabulator_presets';
|
||||
|
||||
$qry = 'GRANT USAGE ON public.seq_tbl_tabulator_presets_preset_id TO vilesci;';
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>public.tbl_tabulator_presets: ' . $db->db_last_error() . '</strong><br>';
|
||||
else
|
||||
echo '<br>Granted privileges to <strong>vilesci</strong> on public.tbl_tabulator_presets';
|
||||
}
|
||||
+753
-1
@@ -41556,6 +41556,26 @@ array(
|
||||
)
|
||||
),
|
||||
// grades
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'stv',
|
||||
'phrase' => 'grades_gradelist',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Studienverlauf',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Grade list',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'stv',
|
||||
@@ -49804,7 +49824,7 @@ array(
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'stv',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'weitereEMail',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
@@ -61599,6 +61619,738 @@ I have been informed that I am under no obligation to consent to the transmissio
|
||||
)
|
||||
)
|
||||
),
|
||||
//Start Finetuning StudVW
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'fenster_schliessen',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Sie können nun das Fenster schließen',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'This window can be closed now',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tag',
|
||||
'phrase' => 'rebuild_tags',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Neuberechnen Tags',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Rebuild Tags',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'selection',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Auswahl',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'selection',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tag',
|
||||
'phrase' => 'messageModalWait',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Bitte warten Sie, bis alle Tags neu berechnet wurden!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Please wait until all tags have been recalculated!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tag',
|
||||
'phrase' => 'alertSuccessRebuild',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Tags erfolgreich neuberechnet ({count} Prestudent*innnen)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Tags successfully recalculated ({count} prestudents)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tag',
|
||||
'phrase' => 'alertErrorRebuild',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Fehler bei Neuberechnen Tags, PrestudentId(s): ',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Error during Recalculating tags, PrestudentId(s): ',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
//End Finetuning StudVW
|
||||
// tabulator presets section phrases START
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'displayed_columns',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Angezeigte Spalten',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Displayed columns',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'in_order',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'in Reihenfolge',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'in order',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'column_header_filters',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Spalten Header Filter',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Column header filters',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'asc',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'aufsteigend',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'ascending',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'desc',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'absteigend',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'descending',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'sort',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Sortierung',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Sort',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'preset_deletion_confirmation',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Sind Sie sicher, dass Sie die Voreinstellung (((presetName))) löschen möchten?',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Are you sure you want to delete preset (((presetName)))?',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'table_presets',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Tabelle Voreinstellungen',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Table presets',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'save_current_config',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Aktuelle Einstellung speichern',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Save current configuration',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'preset_name',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Voreinstellung Name',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Preset name',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'max_presets_count_err_msg',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Maximale Anzahl an Voreinstellungen erreicht!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Maximum number of presets reached!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'preset_name_duplicate_err_msg',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Doppelte Voreinstellunge Namen sind nicht zulässig!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Preset name duplicate not allowed!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'preset_not_found_err_msg',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Voreinstellung nicht gefunden!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Preset not found!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'preset_not_own_update_err_msg',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Sie dürfen diese Voreinstellung nicht ändern!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'You are not allowed to update this preset!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'preset_not_own_delete_err_msg',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Sie dürfen diese Voreinstellung nicht löschen!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'You are not allowed to delete this preset!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'preset_creation_generic_err_msg',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Bei der Erstellung der Voreinstellung ist ein Fehler aufgetreten!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Something went wrong during preset creation!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'preset_update_generic_err_msg',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Bei der Voreinstellungsänderung ist ein Fehler aufgetreten!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Something went wrong during preset update!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'preset_deletion_generic_err_msg',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Beim Löschen der Voreinstellung ist ein Fehler aufgetreten!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Something went wrong during preset deletion!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'invalid_params_err_msg',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Ungültige Parameterübergabe!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Invalid parameters!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'tabulator_presets',
|
||||
'phrase' => 'modified',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'modifiziert',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'modified',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
// tabulator presets section phrases END
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'openInMailClient',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'In Mailanwendung öffnen',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Open in Mailclient',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'kompatibilityMode_WebmailClient',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Kompatibilitätsmodus für Webmail',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Open in Compatibility mode (Webmail)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'webmailclient',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Webmail',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'webmail',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
// StudVw legacy Bis Links begin
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'stv',
|
||||
'phrase' => 'bis_stud',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'BIS (Studierende)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'BIS (Students)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'stv',
|
||||
'phrase' => 'bis_stud_meldung',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Meldung generieren (Studierende)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Generate Report (Students)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'stv',
|
||||
'phrase' => 'bis_stud_plausicheck',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Plausibilitätsprüfung (Studierende)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Plausibility Check (Students)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'alert_chooseDegreeProgram',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Bitte einen Studiengang auswählen!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Please select a degree program!',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
// StudVw legacy Bis Links ende
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'studierendenantrag',
|
||||
'phrase' => 'link_Abmeldung',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Weiter zur Abmeldung',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Continue to De-registration',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'studierendenantrag',
|
||||
'phrase' => 'modalHinweistext_Abmeldung',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Bevor du deine Abmeldung abschließt, möchten wir dir gerne ein Gespräch anbieten. Vielleicht gibt es Fragen, Unsicherheiten oder Herausforderungen, bei denen wir dich unterstützen können.<br>
|
||||
<br>Du kannst dich jederzeit unverbindlich an deine Studiengangsassistenz, Studiengangsleitung oder das <a href='https://cis.technikum-wien.at/cis.php/CisVue/Cms/content/9248' target='_blank'>Student Support Team</a> wenden. Ein Gespräch ist natürlich freiwillig – manchmal hilft es aber, gemeinsam Optionen zu besprechen, zum Beispiel auch eine vorübergehende
|
||||
<a href={linkUnterbrechung} target='_blank'>Studienunterbrechung</a>.
|
||||
<br><br>Wenn du deine Abmeldung fortsetzen möchtest, kannst du das selbstverständlich tun.",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "Before you finalize your deregistration, we would like to offer you a consultation. Perhaps you have questions, uncertainties, or challenges that we can help you with. <br>
|
||||
<br>You can contact your program assistant, program director, or the <a href='https://cis.technikum-wien.at/cis.php/CisVue/Cms/content/9248' target='_blank'>Student Support Team</a> at any time without obligation. A consultation is, of course, voluntary; however, sometimes it helps to discuss options together, such as a
|
||||
<a href={linkUnterbrechung} target='_blank'>temporary break</a> from your studies.
|
||||
<br><br>If you wish to proceed with your deregistration, you can, of course, do so.",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'studierendenantrag',
|
||||
'phrase' => 'info_consultation',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Hinweis Beratungsgespräch',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Note Consultation',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user