mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-23 09:52:22 +00:00
Compare commits
151 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bfdec12c0e | |||
| 179386bea9 | |||
| 8ae3afa98a | |||
| fdbb93a5c5 | |||
| 04dc1eb07b | |||
| 50b229090b | |||
| 2d27a998c4 | |||
| 090e535466 | |||
| c4d35181db | |||
| 0ac6ef4599 | |||
| cb60ddcc94 | |||
| bd4ced9559 | |||
| a04d2acb86 | |||
| de2aabf00b | |||
| 685fc69e5d | |||
| 552faefa51 | |||
| 954397f028 | |||
| 80faa61c91 | |||
| 961ede66a9 | |||
| 6fec8382b5 | |||
| 4eb076d115 | |||
| 7427aa87ea | |||
| 85043e57db | |||
| 5beddbccb4 | |||
| e2ae9b88c8 | |||
| ca3abf9154 | |||
| f863c6d728 | |||
| 92a2053b42 | |||
| 70602be54e | |||
| dac71f597a | |||
| 3a646ffe77 | |||
| 26db4a5e7a | |||
| 98a10a2f55 | |||
| e48b94b858 | |||
| 0ff29ba6af | |||
| ba543448ae | |||
| f121f9b5a2 | |||
| 88b22f5490 | |||
| 4b7ee9abe1 | |||
| d499619cf3 | |||
| f489153ff3 | |||
| 9b79a07fa2 | |||
| 6ce14a25d7 | |||
| c701d92779 | |||
| 73e03ba901 | |||
| 95a7797ae9 | |||
| 3ce3eff022 | |||
| 3a91b12f31 | |||
| ea0a249612 | |||
| 843894405e | |||
| 8fddbc3a32 | |||
| b2538075ee | |||
| 5c463c0866 | |||
| 423bbd95a6 | |||
| 386cc779bf | |||
| 08c6d58a50 | |||
| 3f53c5feba | |||
| 298dbbf400 | |||
| 2c057aad58 | |||
| c2ce831bca | |||
| 21c1f13b28 | |||
| e0079bb812 | |||
| 966d1d10f6 | |||
| 76936ad74f | |||
| 6fbb09eb6e | |||
| cfe1307018 | |||
| 5139c3e44e | |||
| 627a52e3d1 | |||
| 1951cd6fa8 | |||
| e3093bdf3f | |||
| b11d8d056a | |||
| 3a4015eced | |||
| aeb5d40840 | |||
| 49c712a5b6 | |||
| 46817b846a | |||
| 8c75608eaf | |||
| 2720ed9ffb | |||
| 2fc392c084 | |||
| ca630e94ae | |||
| 9cff50fa3b | |||
| 3d7a6b1ad3 | |||
| f15fd40636 | |||
| 054cf2f258 | |||
| dc067a619b | |||
| 2a762fa4ab | |||
| ccade6ae0e | |||
| 6971aed030 | |||
| 60e556b2a8 | |||
| 42fbbc5257 | |||
| d01dedb79c | |||
| 1972b461e7 | |||
| e957926a4d | |||
| bac2c13da3 | |||
| b90c26412a | |||
| 65c7ad2aac | |||
| 126a2d3b7b | |||
| 60734f708e | |||
| 9e6c15a10d | |||
| 14a8e2f001 | |||
| 7603f8f12b | |||
| 059b13938e | |||
| a4f2502fe6 | |||
| 7c1762d467 | |||
| 96745525f1 | |||
| 4a4731e619 | |||
| 8d6e04ea77 | |||
| d9e5acb52c | |||
| 6ec32b0ca3 | |||
| 4778bb82c3 | |||
| e20ff52f5b | |||
| df05af98d2 | |||
| 0e4c7dcd14 | |||
| 0764a597af | |||
| 8c36fe585a | |||
| 5ef1dccfc9 | |||
| d4b81da437 | |||
| b91efb6189 | |||
| 6d28b8986d | |||
| a68b730ce0 | |||
| b43f1ec920 | |||
| cdcc734401 | |||
| c3d20bb181 | |||
| f9b9fc1124 | |||
| 6b816def31 | |||
| 5fbcf588ed | |||
| fc4e79c1f5 | |||
| 41b2a6d1d4 | |||
| 976ef1f975 | |||
| e054f1222b | |||
| 56a6aa993e | |||
| db75cd2f62 | |||
| c57eb1b8de | |||
| f3986688f2 | |||
| f1dbc6ab7d | |||
| f42ef3d5b6 | |||
| d1015956d1 | |||
| 726fce9fac | |||
| c47a1cb627 | |||
| a57df7862c | |||
| f068b56083 | |||
| fa7a125727 | |||
| 27a91de5f6 | |||
| 7ccc26c878 | |||
| 9ebc847e8e | |||
| 511b04c1f8 | |||
| ec90d35e02 | |||
| 4f104523ff | |||
| 02153e469f | |||
| 38e8f91fdf | |||
| ba6224bc78 | |||
| d542cf7720 |
@@ -119,6 +119,15 @@ $config['navigation_header'] = array(
|
||||
'requiredPermissions' => array(
|
||||
'lehre/zgvpruefung:r'
|
||||
)
|
||||
),
|
||||
'ferien' => array(
|
||||
'link' => site_url('lehre/Ferienverwaltung'),
|
||||
'description' => 'Ferienverwaltung',
|
||||
'expand' => true,
|
||||
'sort' => 55,
|
||||
'requiredPermissions' => array(
|
||||
'basis/ferien:r'
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
@@ -208,7 +217,14 @@ $config['navigation_header'] = array(
|
||||
'expand' => true,
|
||||
'sort' => 30,
|
||||
'requiredPermissions' => 'lehre/anrechnungszeitfenster:rw'
|
||||
)
|
||||
),
|
||||
'dashboardadmin' => array(
|
||||
'link' => site_url('dashboard/Admin'),
|
||||
'description' => 'Dashboard Admin',
|
||||
'expand' => true,
|
||||
'sort' => 40,
|
||||
'requiredPermissions' => 'dashboard/admin:r'
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -511,10 +511,11 @@ class Abgabe extends FHCAPI_Controller
|
||||
return $projektarbeit->projektarbeit_id;
|
||||
};
|
||||
$projektarbeiten_ids = array_map($mapFunc, $projektarbeiten->retval);
|
||||
|
||||
$ret = $this->ProjektarbeitModel->getProjektarbeitenAbgabetermine($projektarbeiten_ids);
|
||||
$projektabgaben = $this->getDataOrTerminateWithError($ret, 'general');
|
||||
|
||||
if(count($projektarbeiten_ids) > 0) {
|
||||
$ret = $this->ProjektarbeitModel->getProjektarbeitenAbgabetermine($projektarbeiten_ids);
|
||||
$projektabgaben = $this->getDataOrTerminateWithError($ret, 'general');
|
||||
}
|
||||
|
||||
forEach($projektarbeiten->retval as $pa) {
|
||||
|
||||
@@ -846,9 +847,10 @@ class Abgabe extends FHCAPI_Controller
|
||||
private function getProjektbetreuerEmailByProjektarbeitID($projektarbeit_id) {
|
||||
$this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel');
|
||||
$result = $this->ProjektarbeitModel->getProjektbetreuerEmail($projektarbeit_id);
|
||||
$email = $this->getDataOrTerminateWithError($result, 'general');
|
||||
|
||||
return $email[0]->uid ? $email[0]->uid.'@'.DOMAIN : $email[0]->private_email;
|
||||
if(count($result->retval) > 0) {
|
||||
$email = getData($result);
|
||||
return $email[0]->uid ? $email[0]->uid.'@'.DOMAIN : $email[0]->private_email;
|
||||
} else return '';
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -208,7 +208,6 @@ class Documents extends FHCAPI_Controller
|
||||
$this->load->model('system/Vorlage_model', 'VorlageModel');
|
||||
|
||||
$result = $this->VorlageModel->load($xsl);
|
||||
$this->addMeta("ress", $result);
|
||||
$vorlage = current($this->getDataOrTerminateWithError($result));
|
||||
if (!$vorlage)
|
||||
show_404();
|
||||
@@ -221,7 +220,7 @@ class Documents extends FHCAPI_Controller
|
||||
'gedruckt' => true,
|
||||
'insertamum' => date('c'),
|
||||
'insertvon' => getAuthUID(),
|
||||
'uid' => $this->input->post_get('uid') ?: '',
|
||||
'uid' => $this->input->post_get('uid') ?: null,
|
||||
'archiv' => true,
|
||||
'signiert' => !!$sign_user,
|
||||
'stud_selfservice' => $vorlage->stud_selfservice
|
||||
@@ -251,6 +250,9 @@ class Documents extends FHCAPI_Controller
|
||||
'studiensemester_kurzbz' => $ss,
|
||||
'student_uid' => $akteData['uid']
|
||||
]);
|
||||
|
||||
if (!hasData($result)) $this->terminateWithError($this->p->t("stv", "error_noLehrverbandAssigned"));
|
||||
|
||||
$res = current($this->getDataOrTerminateWithError($result));
|
||||
|
||||
$studiengang_kz = $res->studiengang_kz;
|
||||
@@ -332,6 +334,7 @@ class Documents extends FHCAPI_Controller
|
||||
if ($prestudent_id) {
|
||||
$this->load->model('crm/prestudent_model', 'PrestudentModel');
|
||||
$this->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz', 'LEFT');
|
||||
$this->PrestudentModel->addSelect('tbl_prestudent.*, UPPER(typ || kurzbz) AS kuerzel');
|
||||
$result = $this->PrestudentModel->load($prestudent_id);
|
||||
$prestudent = current($this->getDataOrTerminateWithError($result));
|
||||
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
/**
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* This controller operates between (interface) the JS (GUI) and the back-end
|
||||
* Provides data to the ajax get calls about addresses
|
||||
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
|
||||
*/
|
||||
class Board extends FHCAPI_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'list' => 'dashboard/admin:r',
|
||||
'create' => 'dashboard/admin:rw',
|
||||
'update' => 'dashboard/admin:rw',
|
||||
'delete' => 'dashboard/admin:rw'
|
||||
]);
|
||||
|
||||
// Models
|
||||
$this->load->model('dashboard/Dashboard_model', 'DashboardModel');
|
||||
}
|
||||
|
||||
public function list()
|
||||
{
|
||||
$result = $this->DashboardModel->load();
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$dashboard_kurzbz = $this->input->post('dashboard_kurzbz');
|
||||
|
||||
$result = $this->DashboardModel->insert([
|
||||
'dashboard_kurzbz' => $dashboard_kurzbz
|
||||
]);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('dashboard_id', 'Dashboard ID', 'required');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$dashboard_id = $this->input->post('dashboard_id');
|
||||
$dashboard_kurzbz = $this->input->post('dashboard_kurzbz');
|
||||
$beschreibung = $this->input->post('beschreibung');
|
||||
|
||||
$result = $this->DashboardModel->update([
|
||||
'dashboard_id' => $dashboard_id
|
||||
], [
|
||||
'dashboard_kurzbz' => $dashboard_kurzbz,
|
||||
'beschreibung' => $beschreibung
|
||||
]);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('dashboard_id', 'Dashboard ID', 'required');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$dashboard_id = $this->input->post('dashboard_id');
|
||||
|
||||
//delete all presets
|
||||
$this->load->model('dashboard/Dashboard_Preset_model', 'DashboardPresetModel');
|
||||
|
||||
$result = $this->DashboardPresetModel->delete([
|
||||
'dashboard_id' => $dashboard_id
|
||||
]);
|
||||
$this->getDataOrTerminateWithError($result);
|
||||
|
||||
//delete all widgets
|
||||
$this->load->model('dashboard/Dashboard_Widget_model', 'DashboardWidgetModel');
|
||||
|
||||
$result = $this->DashboardWidgetModel->delete([
|
||||
'dashboard_id' => $dashboard_id
|
||||
]);
|
||||
$this->getDataOrTerminateWithError($result);
|
||||
|
||||
$result = $this->DashboardModel->delete($dashboard_id);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
/**
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* This controller operates between (interface) the JS (GUI) and the back-end
|
||||
* Provides data to the ajax get calls about addresses
|
||||
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
|
||||
*/
|
||||
class Preset extends FHCAPI_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'list' => 'dashboard/admin:r',
|
||||
'getBatch' => 'dashboard/admin:r',
|
||||
'addWidget' => 'dashboard/admin:rw',
|
||||
'removeWidget' => 'dashboard/admin:rw'
|
||||
]);
|
||||
|
||||
// Load language phrases
|
||||
$this->loadPhrases([
|
||||
'ui'
|
||||
]);
|
||||
|
||||
// Libraries
|
||||
$this->load->library('dashboard/DashboardLib');
|
||||
|
||||
// Models
|
||||
$this->load->model('ressource/Funktion_model', 'FunktionModel');
|
||||
}
|
||||
|
||||
public function list($dashboard_kurzbz)
|
||||
{
|
||||
$sql = "
|
||||
WITH
|
||||
dashboard_presets AS (
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
dashboard.tbl_dashboard_preset dp
|
||||
JOIN
|
||||
dashboard.tbl_dashboard d ON d.dashboard_id = dp.dashboard_id
|
||||
WHERE
|
||||
d.dashboard_kurzbz = {$this->db->escape($dashboard_kurzbz)}
|
||||
),
|
||||
general AS (
|
||||
SELECT
|
||||
'general' AS funktion_kurzbz,
|
||||
'Allgemein' AS beschreibung
|
||||
)
|
||||
|
||||
(
|
||||
SELECT
|
||||
f.funktion_kurzbz,
|
||||
f.beschreibung,
|
||||
COUNT(p.preset_id) AS has_preset
|
||||
FROM
|
||||
general f
|
||||
LEFT JOIN
|
||||
dashboard_presets p ON p.funktion_kurzbz IS NULL
|
||||
GROUP BY
|
||||
f.funktion_kurzbz, f.beschreibung
|
||||
)
|
||||
UNION ALL
|
||||
(
|
||||
SELECT
|
||||
f.funktion_kurzbz,
|
||||
f.beschreibung,
|
||||
COUNT(p.preset_id) AS has_preset
|
||||
FROM
|
||||
public.tbl_funktion f
|
||||
LEFT JOIN
|
||||
dashboard_presets p ON p.funktion_kurzbz = f.funktion_kurzbz
|
||||
GROUP BY
|
||||
f.funktion_kurzbz, f.beschreibung
|
||||
ORDER BY
|
||||
f.beschreibung ASC
|
||||
)
|
||||
";
|
||||
|
||||
$result = $this->FunktionModel->execReadOnlyQuery($sql);
|
||||
|
||||
$funktionen = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($funktionen);
|
||||
}
|
||||
|
||||
public function getBatch()
|
||||
{
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('db', 'Dashboard', 'required');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$db = $this->input->post('db');
|
||||
$funktionen = $this->input->post('funktionen') ?: [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($funktionen as $funktion) {
|
||||
$conf = $this->dashboardlib->getPreset($db, $funktion);
|
||||
if ($conf) {
|
||||
$preset = json_decode($conf->preset, true);
|
||||
if (!isset($preset[$funktion]) || !isset($preset[$funktion]['widgets']))
|
||||
$result[$funktion] = [];
|
||||
else
|
||||
$result[$funktion] = $preset[$funktion]['widgets'];
|
||||
} else {
|
||||
$result[$funktion] = [];
|
||||
}
|
||||
}
|
||||
|
||||
return $this->terminateWithSuccess($result);
|
||||
}
|
||||
|
||||
public function addWidget()
|
||||
{
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('dashboard', 'Dashboard', 'required');
|
||||
$this->form_validation->set_rules('funktion_kurzbz', 'Funktion', 'required');
|
||||
$this->form_validation->set_rules('widget[widget]', 'Widget', 'required');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$dashboard_kurzbz = $this->input->post('dashboard');
|
||||
$funktion_kurzbz = $this->input->post('funktion_kurzbz');
|
||||
$widget = $this->input->post('widget');
|
||||
|
||||
if (!isset($widget['widgetid']))
|
||||
$widget['widgetid'] = $this->dashboardlib->generateWidgetId($dashboard_kurzbz);
|
||||
|
||||
$preset = $this->dashboardlib->getPresetOrCreateEmptyPreset($dashboard_kurzbz, $funktion_kurzbz);
|
||||
|
||||
$preset_decoded = json_decode($preset->preset, true);
|
||||
|
||||
$this->dashboardlib->addWidgetsToWidgets($preset_decoded, $dashboard_kurzbz, $funktion_kurzbz, [$widget]);
|
||||
|
||||
$preset->preset = json_encode($preset_decoded);
|
||||
|
||||
$result = $this->dashboardlib->insertOrUpdatePreset($preset);
|
||||
|
||||
$this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($widget['widgetid']);
|
||||
}
|
||||
|
||||
public function removeWidget()
|
||||
{
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('db', 'Dashboard', 'required');
|
||||
$this->form_validation->set_rules('funktion_kurzbz', 'Funktion', 'required');
|
||||
$this->form_validation->set_rules('widgetid', 'Widget', 'required');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$dashboard_kurzbz = $this->input->post('db');
|
||||
$funktion_kurzbz = $this->input->post('funktion_kurzbz');
|
||||
$widgetid = $this->input->post('widgetid');
|
||||
|
||||
$preset = $this->dashboardlib->getPreset($dashboard_kurzbz, $funktion_kurzbz);
|
||||
if (!$preset)
|
||||
show_404();
|
||||
|
||||
$preset_decoded = json_decode($preset->preset, true);
|
||||
|
||||
if (!$this->dashboardlib->removeWidgetFromWidgets($preset_decoded, $funktion_kurzbz, $widgetid))
|
||||
show_404();
|
||||
|
||||
$preset->preset = json_encode($preset_decoded);
|
||||
|
||||
$result = $this->dashboardlib->insertOrUpdatePreset($preset);
|
||||
|
||||
$this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess(array('msg' => $this->p->t('dashboard', 'success_savePreset')));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
/**
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* This controller operates between (interface) the JS (GUI) and the back-end
|
||||
* Provides data to the ajax get calls about the users dashboard
|
||||
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
|
||||
*/
|
||||
class User extends FHCAPI_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'get' => 'dashboard/benutzer:r',
|
||||
'addWidget' => 'dashboard/benutzer:rw',
|
||||
'removeWidget' => 'dashboard/benutzer:rw'
|
||||
]);
|
||||
|
||||
// Libraries
|
||||
$this->load->library('dashboard/DashboardLib');
|
||||
|
||||
// Models
|
||||
$this->load->model('ressource/Funktion_model', 'FunktionModel');
|
||||
}
|
||||
|
||||
public function get($dashboard_kurzbz)
|
||||
{
|
||||
$dashboard = $this->dashboardlib->getDashboardByKurzbz($dashboard_kurzbz);
|
||||
if (!$dashboard)
|
||||
show_404();
|
||||
|
||||
$uid = $this->authlib->getAuthObj()->username;
|
||||
|
||||
/*$mergedconfig = $this->dashboardlib->getMergedConfig($dashboard->dashboard_id, $uid);
|
||||
|
||||
$this->terminateWithSuccess([
|
||||
'general' => call_user_func_array(
|
||||
'array_merge_recursive',
|
||||
$mergedconfig
|
||||
)
|
||||
]);*/
|
||||
$defaultconfig = $this->dashboardlib->getDefaultConfig($dashboard->dashboard_id);
|
||||
$userconfig = $this->dashboardlib->getUserConfig($dashboard->dashboard_id, $uid);
|
||||
|
||||
$defaultconfig_squashed = $defaultconfig ? call_user_func_array('array_replace_recursive', $defaultconfig) : [];
|
||||
$userconfig_squashed = $userconfig ? call_user_func_array('array_replace_recursive', $userconfig) : [];
|
||||
|
||||
$mergedconfig = array_replace_recursive($defaultconfig_squashed, $userconfig_squashed);
|
||||
|
||||
$this->terminateWithSuccess([
|
||||
DashboardLib::SECTION_IF_FUNKTION_KURZBZ_IS_NULL => $mergedconfig
|
||||
]);
|
||||
}
|
||||
|
||||
public function addWidget()
|
||||
{
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('dashboard', 'Dashboard', 'required');
|
||||
$this->form_validation->set_rules('widget[widget]', 'Widget', 'required');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$widget = $this->input->post('widget');
|
||||
$dashboard_kurzbz = $this->input->post('dashboard');
|
||||
$uid = $this->authlib->getAuthObj()->username;
|
||||
|
||||
if (!isset($widget['widgetid']))
|
||||
$widget['widgetid'] = $this->dashboardlib->generateWidgetId($dashboard_kurzbz);
|
||||
|
||||
$override = $this->dashboardlib->getOverrideOrCreateEmptyOverride($dashboard_kurzbz, $uid);
|
||||
|
||||
$override_decoded = json_decode($override->override, true);
|
||||
|
||||
if (!isset($override_decoded['general']) || !is_array($override_decoded['general']))
|
||||
$override_decoded['general'] = [];
|
||||
|
||||
if (!isset($override_decoded['general']['widgets']))
|
||||
$override_decoded['general']['widgets'] = [];
|
||||
|
||||
$override_decoded['general']['widgets'][$widget['widgetid']] = $widget;
|
||||
|
||||
// NOTE(chris): remove doubles in other funktionen
|
||||
foreach ($override_decoded as $funktion => $array) {
|
||||
if ($funktion == 'general')
|
||||
continue;
|
||||
if (isset($array['widgets']) && isset($array['widgets'][$widget['widgetid']]))
|
||||
unset($override_decoded[$funktion]['widgets'][$widget['widgetid']]);
|
||||
}
|
||||
|
||||
$override->override = json_encode($override_decoded);
|
||||
|
||||
$result = $this->dashboardlib->insertOrUpdateOverride($override);
|
||||
|
||||
$this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($widget['widgetid']);
|
||||
}
|
||||
|
||||
public function removeWidget()
|
||||
{
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('dashboard', 'Dashboard', 'required');
|
||||
$this->form_validation->set_rules('widget', 'Widget', 'required');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$widget_id = $this->input->post('widget');
|
||||
$dashboard_kurzbz = $this->input->post('dashboard');
|
||||
$uid = $this->authlib->getAuthObj()->username;
|
||||
|
||||
$override = $this->dashboardlib->getOverride($dashboard_kurzbz, $uid);
|
||||
if (!$override)
|
||||
show_404();
|
||||
|
||||
$override_decoded = json_decode($override->override, true);
|
||||
|
||||
foreach (array_keys($override_decoded) as $k) {
|
||||
if (!isset($override_decoded[$k]["widgets"])) {
|
||||
unset($override_decoded[$k]);
|
||||
continue;
|
||||
}
|
||||
if (isset($override_decoded[$k]["widgets"][$widget_id])) {
|
||||
unset($override_decoded[$k]["widgets"][$widget_id]);
|
||||
}
|
||||
if (!$override_decoded[$k]["widgets"]) {
|
||||
unset($override_decoded[$k]);
|
||||
}
|
||||
}
|
||||
|
||||
$override->override = json_encode($override_decoded);
|
||||
|
||||
$result = $this->dashboardlib->insertOrUpdateOverride($override);
|
||||
|
||||
$this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
/**
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* This controller operates between (interface) the JS (GUI) and the back-end
|
||||
* Provides data to the ajax get calls about the users dashboard
|
||||
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
|
||||
*/
|
||||
class Widget extends FHCAPI_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'get' => ['dashboard/benutzer:r', 'dashboard/admin:r'],
|
||||
'list' => 'dashboard/admin:r',
|
||||
'listAllowed' => ['dashboard/benutzer:rw', 'dashboard/admin:r'],
|
||||
'setAllowed' => 'dashboard/admin:rw'
|
||||
]);
|
||||
|
||||
// Libraries
|
||||
$this->load->library('dashboard/DashboardLib');
|
||||
|
||||
// Models
|
||||
$this->load->model('dashboard/Widget_model', 'WidgetModel');
|
||||
}
|
||||
|
||||
public function get($id)
|
||||
{
|
||||
$result = $this->WidgetModel->load($id);
|
||||
|
||||
$widget = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
if (!$widget)
|
||||
return $this->terminateWithSuccess([
|
||||
"widget_id" => 0,
|
||||
"widget_kurzbz" => "notfound",
|
||||
"arguments" => [
|
||||
"className" => 'alert-danger',
|
||||
"title" => 'Widget Not Found',
|
||||
"msg" => 'The widget with the id ' . $id . ' could not be found'
|
||||
],
|
||||
"setup" => [
|
||||
"name" => 'Widget Not Found',
|
||||
"file" => absoluteJsImportUrl('public/js/components/DashboardWidget/Default.js'),
|
||||
"width" => 1,
|
||||
"height" => 1
|
||||
]
|
||||
]);
|
||||
|
||||
$widget = current($widget);
|
||||
$widget->arguments = json_decode($widget->arguments);
|
||||
$tmpsetup = json_decode($widget->setup);
|
||||
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
|
||||
$widget->setup = $tmpsetup;
|
||||
|
||||
$this->terminateWithSuccess($widget);
|
||||
}
|
||||
|
||||
public function list($dashboard)
|
||||
{
|
||||
$result = $this->WidgetModel->getWithAllowedForDashboard($dashboard);
|
||||
|
||||
$widgets = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$widgets = array_map(function ($widget) {
|
||||
$widget->arguments = json_decode($widget->arguments);
|
||||
$tmpsetup = json_decode($widget->setup);
|
||||
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
|
||||
$widget->setup = $tmpsetup;
|
||||
return $widget;
|
||||
}, $widgets);
|
||||
|
||||
$this->terminateWithSuccess($widgets);
|
||||
}
|
||||
|
||||
public function listAllowed($dashboard)
|
||||
{
|
||||
$result = $this->WidgetModel->getForDashboard($dashboard);
|
||||
|
||||
$widgets = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$widgets = array_map(function ($widget) {
|
||||
$widget->arguments = json_decode($widget->arguments);
|
||||
$tmpsetup = json_decode($widget->setup);
|
||||
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
|
||||
$widget->setup = $tmpsetup;
|
||||
return $widget;
|
||||
}, $widgets);
|
||||
|
||||
$this->terminateWithSuccess($widgets);
|
||||
}
|
||||
|
||||
public function setAllowed()
|
||||
{
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('dashboard_id', 'Dashboard', 'required');
|
||||
$this->form_validation->set_rules('widget_id', 'Widget', 'required');
|
||||
$this->form_validation->set_rules('allowed', 'Allowed', 'is_bool');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$data = [
|
||||
'dashboard_id' => $this->input->post('dashboard_id'),
|
||||
'widget_id' => $this->input->post('widget_id')
|
||||
];
|
||||
|
||||
$this->load->model('dashboard/Dashboard_Widget_model', 'DashboardWidgetModel');
|
||||
|
||||
if ($this->input->post('allowed'))
|
||||
$result = $this->DashboardWidgetModel->insert($data);
|
||||
else
|
||||
$result = $this->DashboardWidgetModel->delete($data);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,371 @@
|
||||
<?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');
|
||||
|
||||
//use CI3_Events as Events;
|
||||
|
||||
/**
|
||||
* This controller operates between (interface) the JS (GUI) and the back-end
|
||||
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
|
||||
*/
|
||||
class Ferien extends FHCAPI_Controller
|
||||
{
|
||||
const DEFAULT_BERECHTIGUNG = 'basis/ferien';
|
||||
|
||||
/**
|
||||
* Calls the parent's constructor and prepares libraries and phrases
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getFerien' => self::DEFAULT_BERECHTIGUNG.':r',
|
||||
'getDefaultVonBis' => self::DEFAULT_BERECHTIGUNG.':r',
|
||||
'getOe' => self::DEFAULT_BERECHTIGUNG.':r',
|
||||
'getStudienplaene' => self::DEFAULT_BERECHTIGUNG.':r',
|
||||
'getFerientypen' => self::DEFAULT_BERECHTIGUNG.':r',
|
||||
'insert' => self::DEFAULT_BERECHTIGUNG.':w',
|
||||
'update' => self::DEFAULT_BERECHTIGUNG.':w',
|
||||
'delete' => self::DEFAULT_BERECHTIGUNG.':w'
|
||||
]);
|
||||
|
||||
// Load models
|
||||
$this->load->model('organisation/Ferien_model', 'FerienModel');
|
||||
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
|
||||
|
||||
$this->load->library('PermissionLib');
|
||||
|
||||
|
||||
// Load language phrases
|
||||
$this->loadPhrases([
|
||||
'ui'
|
||||
]);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* Get Ferien
|
||||
*/
|
||||
public function getFerien()
|
||||
{
|
||||
$filterVonDatum = $this->input->get('filterVonDatum');
|
||||
$filterBisDatum = $this->input->get('filterBisDatum');
|
||||
|
||||
if (isset($filterVonDatum) && !is_valid_date($filterVonDatum))
|
||||
return $this->terminateWithError($this->p->t('ui', 'error_invalid_date'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
if (isset($filterBisDatum) && !is_valid_date($filterBisDatum))
|
||||
return $this->terminateWithError($this->p->t('ui', 'error_invalid_date'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
$this->FerienModel->addSelect(
|
||||
'tbl_ferien.ferien_id, tbl_ferien.bezeichnung, tbl_ferien.vondatum, tbl_ferien.bisdatum,
|
||||
plan.studienplan_id, oe.oe_kurzbz, fetyp.ferientyp_kurzbz, oe.bezeichnung AS oe_bezeichnung,
|
||||
plan.studienplan_id, plan.bezeichnung AS studienplan_bezeichnung, fetyp.mitarbeiter AS mitarbeiterrelevant,
|
||||
fetyp.studierende AS studierendenrelevant, fetyp.lehre'
|
||||
);
|
||||
$this->FerienModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
|
||||
$this->FerienModel->addJoin('lehre.tbl_studienplan plan', 'studienplan_id', 'LEFT');
|
||||
$this->FerienModel->addJoin('public.tbl_organisationseinheit oe', 'tbl_ferien.oe_kurzbz = oe.oe_kurzbz', 'LEFT');
|
||||
$this->FerienModel->addJoin('lehre.tbl_ferientyp fetyp', 'ferientyp_kurzbz', 'LEFT');
|
||||
|
||||
if (isset($filterVonDatum))
|
||||
$this->FerienModel->db->where('tbl_ferien.bisdatum >=', $filterVonDatum);
|
||||
|
||||
if (isset($filterBisDatum))
|
||||
$this->FerienModel->db->where('tbl_ferien.vondatum <=', $filterBisDatum);
|
||||
|
||||
$this->FerienModel->addOrder('vondatum', 'DESC');
|
||||
$result = $this->FerienModel->load();
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets default dates (from - to) for filtering Ferien.
|
||||
*/
|
||||
public function getDefaultVonBis()
|
||||
{
|
||||
$defaultVonBis = ['defaultVon' => null, 'defaultBis' => null];
|
||||
|
||||
// get current Studienjahr
|
||||
$this->load->model('organisation/Studienjahr_model', 'StudienjahrModel');
|
||||
|
||||
$result = $this->StudienjahrModel->getAktOrNextStudienjahr(62);
|
||||
|
||||
if (isError($result)) return $this->terminateWithError(getError($result));
|
||||
|
||||
if (hasData($result))
|
||||
{
|
||||
$studienjahr = getData($result)[0];
|
||||
$defaultVonBis['defaultVon'] = $studienjahr->beginn;
|
||||
$defaultVonBis['defaultBis'] = $studienjahr->ende;
|
||||
}
|
||||
|
||||
$this->terminateWithSuccess($defaultVonBis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of Organisationseinheiten
|
||||
*/
|
||||
public function getOe()
|
||||
{
|
||||
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
|
||||
|
||||
//$this->StudiengangModel->addSelect(' tbl_studiengang.*, UPPER(typ::varchar(1) || kurzbz) AS kuerzel');
|
||||
$this->OrganisationseinheitModel->addOrder('organisationseinheittyp_kurzbz, oe_kurzbz');
|
||||
$result = $this->OrganisationseinheitModel->loadWhere(['aktiv' => true]);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of Studienplaene.
|
||||
* Studienplaene are returned by Organisationseinheit, von and bis datum.
|
||||
*/
|
||||
public function getStudienplaene()
|
||||
{
|
||||
// check input
|
||||
$oe_kurzbz = $this->input->get('oe_kurzbz');
|
||||
$vondatum = $this->input->get('vondatum');
|
||||
$bisdatum = $this->input->get('bisdatum');
|
||||
|
||||
if (!isset($oe_kurzbz) || isEmptyString($oe_kurzbz))
|
||||
return $this->terminateWithError($this->p->t('ferien', 'error_missingId', ['id' => 'Organisationseinheit']));
|
||||
|
||||
if (isset($vondatum) && !is_valid_date($vondatum))
|
||||
return $this->terminateWithError($this->p->t('ui', 'error_invalid_date'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
if (isset($bisdatum) && !is_valid_date($bisdatum))
|
||||
return $this->terminateWithError($this->p->t('ui', 'error_invalid_date'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
// get Studiengang from Oe
|
||||
$result = $this->StudiengangModel->loadWhere(['oe_kurzbz' => $oe_kurzbz]);
|
||||
|
||||
if (isError($result)) return $this->terminateWithError(getError($result));
|
||||
if (!hasData($result)) return $this->terminateWithSuccess([]);
|
||||
$studiengangKzArr = array_column(getData($result), 'studiengang_kz');
|
||||
|
||||
// load models
|
||||
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
|
||||
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
|
||||
|
||||
// get all Studiensemester in requested date range
|
||||
$result = $this->StudiensemesterModel->getByDateRange($vondatum, $bisdatum);
|
||||
if (isError($result)) return $this->terminateWithError(getError($result));
|
||||
if (!hasData($result)) return $this->terminateWithSuccess([]);
|
||||
$studiensemesterArr = array_column(getData($result), 'studiensemester_kurzbz');
|
||||
|
||||
$studienplaene = [];
|
||||
foreach ($studiengangKzArr as $studiengang_kz)
|
||||
{
|
||||
foreach ($studiensemesterArr as $studiensemester_kurzbz)
|
||||
{
|
||||
// get studienplaene for each Studiengang and Studiensemester
|
||||
$this->StudienplanModel->addDistinct("studienplan_id");
|
||||
$this->StudienplanModel->addSelect("lehre.tbl_studienplan.*");
|
||||
$this->StudienplanModel->addJoin("lehre.tbl_studienordnung", "studienordnung_id");
|
||||
$this->StudienplanModel->addJoin("lehre.tbl_studienplan_semester", "studienplan_id");
|
||||
|
||||
$whereArray = array(
|
||||
"tbl_studienplan.aktiv" => "TRUE",
|
||||
"tbl_studienordnung.studiengang_kz" => $studiengang_kz,
|
||||
"tbl_studienplan_semester.studiensemester_kurzbz" => $studiensemester_kurzbz
|
||||
);
|
||||
|
||||
$result = $this->StudienplanModel->loadWhere($whereArray);
|
||||
|
||||
if (isError($result)) return $this->terminateWithError(getError($result));
|
||||
if (!hasData($result)) continue;
|
||||
|
||||
foreach (getData($result) as $studienplan)
|
||||
{
|
||||
$studienplaene[$studienplan->studienplan_id] = $studienplan;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->terminateWithSuccess($studienplaene);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of Ferientypen
|
||||
*/
|
||||
public function getFerientypen()
|
||||
{
|
||||
$this->load->model('organisation/Ferientyp_model', 'FerientypModel');
|
||||
|
||||
$this->FerientypModel->addOrder('ferientyp_kurzbz');
|
||||
$result = $this->FerientypModel->load();
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Ferien
|
||||
*/
|
||||
public function insert()
|
||||
{
|
||||
$this->_validate();
|
||||
|
||||
$data = $this->_getData();
|
||||
|
||||
// check permissions for new Ferien
|
||||
if (!$this->permissionlib->isBerechtigt(self::DEFAULT_BERECHTIGUNG, 'suid', $data['oe_kurzbz']))
|
||||
return $this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
|
||||
|
||||
$data = array_merge($data, ['insertamum' => date('c'), 'insertvon' => getAuthUID()]);
|
||||
|
||||
$id = $this->getDataOrTerminateWithError($this->FerienModel->insert($data));
|
||||
|
||||
$this->terminateWithSuccess(hasData($id) ? getData($id) : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Ferien
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
$id = $this->input->post('ferien_id');
|
||||
|
||||
if (!is_numeric($id))
|
||||
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Ferien Id']), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
$this->_validate();
|
||||
|
||||
$data = $this->_getData();
|
||||
|
||||
// check permissions for existing Ferien
|
||||
$this->_validateBerechtigung('suid', $id);
|
||||
|
||||
// check permissions for new Ferien
|
||||
if (!$this->permissionlib->isBerechtigt(self::DEFAULT_BERECHTIGUNG, 'suid', $data['oe_kurzbz']))
|
||||
return $this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
|
||||
|
||||
if (isEmptyArray($data)) return $this->terminateWithSuccess(null);
|
||||
|
||||
$data = array_merge($data, ['ferien_id' => $id, 'updateamum' => date('c'), 'updatevon' => getAuthUID()]);
|
||||
|
||||
$result = $this->FerienModel->update($id, $data);
|
||||
|
||||
if (isError($result)) return $this->terminateWithError(getError($result));
|
||||
|
||||
$this->terminateWithSuccess($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Ferien
|
||||
*/
|
||||
public function delete()
|
||||
{
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('ferien_id', 'Ferien Id', 'required');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$ferien_id = $this->input->post('ferien_id');
|
||||
|
||||
$this->_validateBerechtigung('suid', $ferien_id);
|
||||
|
||||
$this->FerienModel->addSelect('ferien_id');
|
||||
$result = $this->FerienModel->load($ferien_id);
|
||||
|
||||
if (!hasData($result)) return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['ferien_id' => $ferien_id]));
|
||||
|
||||
$result = $this->getDataOrTerminateWithError($this->FerienModel->delete($ferien_id));
|
||||
|
||||
$this->terminateWithSuccess();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate ferien post input.
|
||||
*/
|
||||
private function _validate()
|
||||
{
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('vondatum', 'Von Datum', 'required|is_valid_date');
|
||||
$this->form_validation->set_rules('bisdatum', 'Bis Datum', 'required|is_valid_date');
|
||||
$this->form_validation->set_rules('bezeichnung', 'Bezeichnung', 'required|max_length[128]');
|
||||
$this->form_validation->set_rules('oe_kurzbz', 'Organisationseinheit', 'max_length[32]');
|
||||
$this->form_validation->set_rules('studienplan_id', 'Studienplan', 'numeric');
|
||||
$this->form_validation->set_rules('ferientyp_kurzbz', 'Ferientyp', 'max_length[64]');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks permission for oe of Ferien. Terminates if unauthorized.
|
||||
* @param typ permission type suid
|
||||
* @param ferien_id
|
||||
* @return void
|
||||
*/
|
||||
private function _validateBerechtigung($typ, $ferien_id)
|
||||
{
|
||||
if (isset($ferien_id))
|
||||
{
|
||||
$this->FerienModel->addSelect('oe_kurzbz');
|
||||
$result = $this->FerienModel->load($ferien_id);
|
||||
|
||||
if (isError($result)) return $this->terminateWithError(getError($result));
|
||||
|
||||
if (hasData($result))
|
||||
{
|
||||
$ferien = getData($result)[0];
|
||||
|
||||
if ($this->permissionlib->isBerechtigt(self::DEFAULT_BERECHTIGUNG, $typ, $ferien->oe_kurzbz)) return;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->terminateWithError($this->p->t('ui', 'keineBerechtigung'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets Ferien data from post input.
|
||||
*/
|
||||
private function _getData()
|
||||
{
|
||||
$data = [];
|
||||
|
||||
$allowed = [
|
||||
'vondatum',
|
||||
'bisdatum',
|
||||
'bezeichnung',
|
||||
'oe_kurzbz',
|
||||
'studienplan_id',
|
||||
'ferientyp_kurzbz'
|
||||
];
|
||||
|
||||
foreach ($allowed as $field)
|
||||
{
|
||||
$data[$field] = $this->input->post($field);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -42,14 +42,22 @@ class Messages extends FHCAPI_Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function getMessages($id, $type_id, $size, $page)
|
||||
public function getMessages($id, $type_id, $size=null, $page=null)
|
||||
{
|
||||
if($type_id != 'person_id'){
|
||||
$id = $this->_getPersonId($id, $type_id);
|
||||
}
|
||||
|
||||
$offset = $size * ($page - 1);
|
||||
$limit = $size;
|
||||
if(!(is_null($size) && is_null($page)))
|
||||
{
|
||||
$offset = $size * ($page - 1);
|
||||
$limit = $size;
|
||||
}
|
||||
else
|
||||
{
|
||||
$offset = null;
|
||||
$limit = null;
|
||||
}
|
||||
|
||||
$result = $this->MessageModel->getMessagesForTable($id, $offset, $limit);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ class NotizPerson extends Notiz_Controller
|
||||
//Load Models
|
||||
$this->load->model('person/Benutzer_model', 'BenutzerModel');
|
||||
$this->load->model('crm/Student_model', 'StudentModel');
|
||||
$this->load->model('crm/Prestudent_model', 'PrestudentModel');
|
||||
|
||||
//Permission checks for allowed Oes
|
||||
if ($this->router->method == 'addNewNotiz')
|
||||
@@ -38,7 +39,7 @@ class NotizPerson extends Notiz_Controller
|
||||
{
|
||||
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID']), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->_checkIfBerechtigungForOneUidExists($person_id, $allowedStgs);
|
||||
$this->_checkIfBerechtigungForOnePrestudentExists($person_id, $allowedStgs);
|
||||
}
|
||||
|
||||
if ( $this->router->method == 'updateNotiz')
|
||||
@@ -59,7 +60,7 @@ class NotizPerson extends Notiz_Controller
|
||||
$person_id = current($data)->person_id;
|
||||
|
||||
$allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: [];
|
||||
$this->_checkIfBerechtigungForOneUidExists($person_id, $allowedStgs);
|
||||
$this->_checkIfBerechtigungForOnePrestudentExists($person_id, $allowedStgs);
|
||||
}
|
||||
|
||||
if ($this->router->method == 'deleteNotiz' )
|
||||
@@ -78,7 +79,7 @@ class NotizPerson extends Notiz_Controller
|
||||
}
|
||||
|
||||
$allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: [];
|
||||
$this->_checkIfBerechtigungForOneUidExists($person_id, $allowedStgs);
|
||||
$this->_checkIfBerechtigungForOnePrestudentExists($person_id, $allowedStgs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,44 +100,20 @@ class NotizPerson extends Notiz_Controller
|
||||
}
|
||||
|
||||
//stv: if person has permission of one studiengang of person -> permission to add/update/delete Note
|
||||
private function _checkIfBerechtigungForOneUidExists($person_id, $allowedStgs)
|
||||
private function _checkIfBerechtigungForOnePrestudentExists($person_id, $allowedStgs)
|
||||
{
|
||||
//get all studentUids of person_id
|
||||
$result = $this->BenutzerModel->loadWhere(['person_id' => $person_id]);
|
||||
$result = $this->PrestudentModel->loadWhere(['person_id' => $person_id]);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$checkarray = [];
|
||||
foreach ($data as $item)
|
||||
{
|
||||
//check if isStudent
|
||||
$result = $this->StudentModel->isStudent($item->uid);
|
||||
|
||||
$isStudent = $this->getDataOrTerminateWithError($result);
|
||||
if($isStudent)
|
||||
if(in_array($item->studiengang_kz, $allowedStgs))
|
||||
{
|
||||
$checkarray[] = $this->_checkAllowedStgsFromUid($item->uid, $allowedStgs);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
if (!in_array(1, $checkarray))
|
||||
return $this->terminateWithError($this->p->t('ui', 'error_keineBerechtigungStg'), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
private function _checkAllowedStgsFromUid($student_uid, $allowedStgs)
|
||||
{
|
||||
$this->load->model('crm/Student_model', 'StudentModel');
|
||||
$result = $this->StudentModel->loadWhere(['student_uid' => $student_uid]);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
$studiengang_kz = current($data)->studiengang_kz;
|
||||
|
||||
if (!in_array($studiengang_kz, $allowedStgs))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
$this->terminateWithError($this->p->t('ui', 'error_keineBerechtigungStg'), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,8 @@ class Konto extends FHCAPI_Controller
|
||||
|
||||
// Load language phrases
|
||||
$this->loadPhrases([
|
||||
'konto'
|
||||
'konto',
|
||||
'lehre'
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -112,7 +113,7 @@ class Konto extends FHCAPI_Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getBuchungstypen()
|
||||
public function getBuchungstypen($studiensemester_kurzbz = null)
|
||||
{
|
||||
$this->load->model('crm/Buchungstyp_model', 'BuchungstypModel');
|
||||
|
||||
@@ -122,6 +123,7 @@ class Konto extends FHCAPI_Controller
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->_getOEHBeitrag($data, $studiensemester_kurzbz);
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
|
||||
@@ -494,4 +496,43 @@ class Konto extends FHCAPI_Controller
|
||||
|
||||
$this->terminateWithSuccess();
|
||||
}
|
||||
|
||||
private function _getOEHBeitrag(&$data, $studiensemester_kurzbz = null)
|
||||
{
|
||||
if (is_null($studiensemester_kurzbz))
|
||||
{
|
||||
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
|
||||
$studiensemester_akt = $this->variablelib->getVar('semester_aktuell');
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
|
||||
if ($this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz))
|
||||
$studiensemester_akt = $studiensemester_kurzbz;
|
||||
else
|
||||
$this->terminateWithError($this->p->t('lehre', 'error_noStudiensemester'));
|
||||
}
|
||||
|
||||
$this->load->model('codex/Oehbeitrag_model', 'OehbeitragModel');
|
||||
$oehBeitrag = $this->OehbeitragModel->getByStudiensemester($studiensemester_akt);
|
||||
|
||||
$oehStandardbetrag = null;
|
||||
if (hasData($oehBeitrag))
|
||||
{
|
||||
$oeh = getData($oehBeitrag)[0];
|
||||
$summe = ($oeh->studierendenbeitrag + $oeh->versicherung) * -1;
|
||||
$oehStandardbetrag = number_format((float)$summe, 2, '.', '');
|
||||
}
|
||||
|
||||
if ($oehStandardbetrag !== null)
|
||||
{
|
||||
$data = array_map(function ($buchungstyp) use ($oehStandardbetrag) {
|
||||
if (isset($buchungstyp->buchungstyp_kurzbz) && (strtolower($buchungstyp->buchungstyp_kurzbz) === 'oeh'))
|
||||
{
|
||||
$buchungstyp->standardbetrag = $oehStandardbetrag;
|
||||
}
|
||||
return $buchungstyp;
|
||||
}, $data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,7 +626,7 @@ class Students extends FHCAPI_Controller
|
||||
$this->addFilter($studiensemester_kurzbz);
|
||||
|
||||
$result = $this->PrestudentModel->loadWhere($where);
|
||||
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
@@ -851,40 +851,44 @@ class Students extends FHCAPI_Controller
|
||||
$stdsemEsc = $studiensemester_kurzbz ? $this->PrestudentModel->escape($studiensemester_kurzbz) : 'NULL';
|
||||
|
||||
$this->load->config('stv');
|
||||
$tags = $this->config->item('stv_prestudent_tags');
|
||||
|
||||
$whereTags = '';
|
||||
if (is_array($tags) && !isEmptyArray($tags)) {
|
||||
$tags = array_keys($tags);
|
||||
if(defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED)
|
||||
{
|
||||
$tags = $this->config->item('stv_prestudent_tags');
|
||||
|
||||
foreach ($tags as $key => $tag) {
|
||||
$tags[$key] = $this->db->escape($tag);
|
||||
$whereTags = '';
|
||||
if (is_array($tags) && !isEmptyArray($tags)) {
|
||||
$tags = array_keys($tags);
|
||||
|
||||
foreach ($tags as $key => $tag) {
|
||||
$tags[$key] = $this->db->escape($tag);
|
||||
}
|
||||
$whereTags = " AND nt.typ_kurzbz IN (" . implode(",", $tags) . ")";
|
||||
}
|
||||
$whereTags = " AND nt.typ_kurzbz IN (" . implode(",", $tags) . ")";
|
||||
$subQueryTag = "
|
||||
(
|
||||
SELECT
|
||||
tag.prestudent_id,
|
||||
COALESCE(json_agg(tag ORDER BY tag.done), '[]'::json) AS tags
|
||||
FROM (
|
||||
SELECT DISTINCT ON (n.notiz_id)
|
||||
n.notiz_id AS id,
|
||||
nt.typ_kurzbz,
|
||||
array_to_json(nt.bezeichnung_mehrsprachig)->>0 AS beschreibung,
|
||||
n.text AS notiz,
|
||||
nt.style,
|
||||
n.erledigt AS done,
|
||||
nz.prestudent_id
|
||||
FROM public.tbl_notizzuordnung AS nz
|
||||
JOIN public.tbl_notiz AS n ON nz.notiz_id = n.notiz_id
|
||||
JOIN public.tbl_notiz_typ AS nt ON n.typ = nt.typ_kurzbz "
|
||||
. $whereTags .
|
||||
"
|
||||
) AS tag
|
||||
GROUP BY tag.prestudent_id
|
||||
) AS tag_data_agg
|
||||
";
|
||||
}
|
||||
$subQueryTag = "
|
||||
(
|
||||
SELECT
|
||||
tag.prestudent_id,
|
||||
COALESCE(json_agg(tag ORDER BY tag.done), '[]'::json) AS tags
|
||||
FROM (
|
||||
SELECT DISTINCT ON (n.notiz_id)
|
||||
n.notiz_id AS id,
|
||||
nt.typ_kurzbz,
|
||||
array_to_json(nt.bezeichnung_mehrsprachig)->>0 AS beschreibung,
|
||||
n.text AS notiz,
|
||||
nt.style,
|
||||
n.erledigt AS done,
|
||||
nz.prestudent_id
|
||||
FROM public.tbl_notizzuordnung AS nz
|
||||
JOIN public.tbl_notiz AS n ON nz.notiz_id = n.notiz_id
|
||||
JOIN public.tbl_notiz_typ AS nt ON n.typ = nt.typ_kurzbz "
|
||||
. $whereTags .
|
||||
"
|
||||
) AS tag
|
||||
GROUP BY tag.prestudent_id
|
||||
) AS tag_data_agg
|
||||
";
|
||||
|
||||
$this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
|
||||
$this->PrestudentModel->addJoin('public.tbl_person p', 'person_id');
|
||||
@@ -907,11 +911,17 @@ class Students extends FHCAPI_Controller
|
||||
AND ps.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')
|
||||
AND ps.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')', 'LEFT');
|
||||
|
||||
$this->PrestudentModel->addJoin($subQueryTag, 'tag_data_agg.prestudent_id = tbl_prestudent.prestudent_id', 'LEFT');
|
||||
if(defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED)
|
||||
{
|
||||
$this->PrestudentModel->addJoin($subQueryTag, 'tag_data_agg.prestudent_id = tbl_prestudent.prestudent_id', 'LEFT');
|
||||
}
|
||||
|
||||
|
||||
$this->PrestudentModel->addSelect("b.uid");
|
||||
$this->PrestudentModel->addSelect('tag_data_agg.tags');
|
||||
if(defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED)
|
||||
{
|
||||
$this->PrestudentModel->addSelect('tag_data_agg.tags');
|
||||
}
|
||||
$this->PrestudentModel->addSelect('titelpre');
|
||||
$this->PrestudentModel->addSelect('nachname');
|
||||
$this->PrestudentModel->addSelect('vorname');
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
*/
|
||||
class Admin extends Auth_Controller
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Set required permissions
|
||||
parent::__construct(
|
||||
array(
|
||||
'index' => 'dashboard/admin:rw',
|
||||
'preview' => 'dashboard/admin:r',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
public function index()
|
||||
{
|
||||
$this->load->view('dashboard/admin.php', []);
|
||||
}
|
||||
|
||||
public function preview($dashboard_kurzbz = 'CIS')
|
||||
{
|
||||
$this->load->view('dashboard/preview.php', [
|
||||
'dashboard_kurzbz' => $dashboard_kurzbz
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
<?php
|
||||
defined('BASEPATH') || exit('No direct script access allowed');
|
||||
|
||||
class Api extends Auth_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
array(
|
||||
'index' => 'dashboard/admin:rw',
|
||||
'getNews' => 'dashboard/benutzer:r',
|
||||
'getAmpeln' => 'dashboard/benutzer:r',
|
||||
)
|
||||
);
|
||||
|
||||
$this->load->library('AuthLib', null, 'AuthLib');
|
||||
|
||||
$this->_setAuthUID();
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
echo 'Dashboard API Controller';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get News.
|
||||
*/
|
||||
public function getNews()
|
||||
{
|
||||
$limit = $this->input->get('limit');
|
||||
|
||||
$this->load->model('content/News_model', 'NewsModel');
|
||||
|
||||
$result = $this->NewsModel->getAll($limit);
|
||||
|
||||
if (hasData($result))
|
||||
{
|
||||
$this->outputJson(getData($result), REST_Controller::HTTP_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->terminateWithJsonError('fehler entdeckt');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get Ampeln.
|
||||
*/
|
||||
public function getAmpeln()
|
||||
{
|
||||
|
||||
$this->load->model('content/Ampel_model', 'AmpelModel');
|
||||
$result = $this->AmpelModel->getByUser($this->_uid);
|
||||
|
||||
if (hasData($result))
|
||||
{
|
||||
$this->outputJson(getData($result), REST_Controller::HTTP_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->terminateWithJsonError('fehler entdeckt');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the UID of the logged user and checks if it is valid
|
||||
*/
|
||||
private function _setAuthUID()
|
||||
{
|
||||
$this->_uid = getAuthUID();
|
||||
|
||||
if (!$this->_uid) show_error('User authentification failed');
|
||||
}
|
||||
}
|
||||
@@ -1,216 +0,0 @@
|
||||
<?php
|
||||
defined('BASEPATH') || exit('No direct script access allowed');
|
||||
/**
|
||||
* Description of Config
|
||||
*
|
||||
* @author bambi
|
||||
*/
|
||||
class Config extends Auth_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
array(
|
||||
'index' => 'dashboard/benutzer:r',
|
||||
'dummy' => 'dashboard/benutzer:r',
|
||||
'genWidgetId' => 'dashboard/benutzer:rw',
|
||||
'addWidgetsToPreset' => 'dashboard/admin:rw',
|
||||
'removeWidgetFromPreset' => 'dashboard/admin:rw',
|
||||
'addWidgetsToUserOverride' => 'dashboard/benutzer:rw',
|
||||
'removeWidgetFromUserOverride' => 'dashboard/benutzer:rw',
|
||||
'funktionen' => 'dashboard/admin:r',
|
||||
'preset' => 'dashboard/admin:r',
|
||||
'presetBatch' => 'dashboard/admin:r'
|
||||
)
|
||||
);
|
||||
|
||||
$this->load->library('dashboard/DashboardLib', null, 'DashboardLib');
|
||||
$this->load->library('AuthLib', null, 'AuthLib');
|
||||
$this->load->model('ressource/Funktion_model', 'FunktionModel');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$dashboard_kurzbz = $this->input->get('db');
|
||||
$uid = $this->AuthLib->getAuthObj()->username;
|
||||
|
||||
$dashboard = $this->DashboardLib->getDashboardByKurzbz($dashboard_kurzbz);
|
||||
if(!$dashboard) {
|
||||
http_response_code(404);
|
||||
$this->terminateWithJsonError(array(
|
||||
'error' => 'Dashboard ' . $dashboard_kurzbz . ' not found.'
|
||||
));
|
||||
}
|
||||
|
||||
$mergedconfig = $this->DashboardLib->getMergedConfig($dashboard->dashboard_id, $uid);
|
||||
$this->outputJsonSuccess($mergedconfig);
|
||||
}
|
||||
|
||||
public function genWidgetId()
|
||||
{
|
||||
$dashboard_kurzbz = $this->input->get('db');
|
||||
$widgetid = $this->DashboardLib->generateWidgetId($dashboard_kurzbz);
|
||||
$this->outputJsonSuccess(array(
|
||||
'widgetid' => $widgetid
|
||||
));
|
||||
}
|
||||
|
||||
public function addWidgetsToPreset()
|
||||
{
|
||||
$input = json_decode($this->input->raw_input_stream);
|
||||
$dashboard_kurzbz = $input->db;
|
||||
$funktion_kurzbz = $input->funktion_kurzbz;
|
||||
|
||||
$preset = $this->DashboardLib->getPresetOrCreateEmptyPreset($dashboard_kurzbz, $funktion_kurzbz);
|
||||
|
||||
$preset_decoded = json_decode($preset->preset, true);
|
||||
|
||||
$this->DashboardLib->addWidgetsToWidgets($preset_decoded, $dashboard_kurzbz, $funktion_kurzbz, $input->widgets);
|
||||
|
||||
$preset->preset = json_encode($preset_decoded);
|
||||
|
||||
$result = $this->DashboardLib->insertOrUpdatePreset($preset);
|
||||
if (isError($result)) {
|
||||
http_response_code(500);
|
||||
$this->terminateWithJsonError('preset could not be saved');
|
||||
}
|
||||
|
||||
$this->outputJsonSuccess(array('msg' => 'preset successfully stored.', 'data' => $preset_decoded));
|
||||
}
|
||||
|
||||
public function removeWidgetFromPreset()
|
||||
{
|
||||
$input = json_decode($this->input->raw_input_stream);
|
||||
$dashboard_kurzbz = $input->db;
|
||||
$funktion_kurzbz = $input->funktion_kurzbz;
|
||||
$widgetid = $input->widgetid;
|
||||
|
||||
$preset = $this->DashboardLib->getPreset($dashboard_kurzbz, $funktion_kurzbz);
|
||||
if ($preset === null) {
|
||||
http_response_code(404);
|
||||
$this->terminateWithJsonError('preset for dashboard ' . $dashboard_kurzbz . ' and funktion ' . $funktion_kurzbz . ' not found.');
|
||||
}
|
||||
|
||||
$preset_decoded = json_decode($preset->preset, true);
|
||||
if (!$this->DashboardLib->removeWidgetFromWidgets($preset_decoded, $funktion_kurzbz, $widgetid))
|
||||
{
|
||||
http_response_code(404);
|
||||
$this->terminateWithJsonError('widgetid ' . $widgetid . ' not found');
|
||||
}
|
||||
|
||||
$preset->preset = json_encode($preset_decoded);
|
||||
$result = $this->DashboardLib->insertOrUpdatePreset($preset);
|
||||
if (isError($result))
|
||||
{
|
||||
http_response_code(500);
|
||||
$this->terminateWithJsonError('failed to remove widget');
|
||||
}
|
||||
$this->outputJsonSuccess(array('msg' => 'preset successfully updated.'));
|
||||
}
|
||||
|
||||
public function addWidgetsToUserOverride()
|
||||
{
|
||||
$input = json_decode($this->input->raw_input_stream);
|
||||
$dashboard_kurzbz = $input->db;
|
||||
$funktion_kurzbz = $input->funktion_kurzbz;
|
||||
$uid = $this->AuthLib->getAuthObj()->username;
|
||||
|
||||
$override = $this->DashboardLib->getOverrideOrCreateEmptyOverride($dashboard_kurzbz, $uid);
|
||||
|
||||
$override_decoded = json_decode($override->override, true);
|
||||
|
||||
$this->DashboardLib->addWidgetsToWidgets($override_decoded, $dashboard_kurzbz, $funktion_kurzbz, $input->widgets);
|
||||
|
||||
$override->override = json_encode($override_decoded);
|
||||
|
||||
$result = $this->DashboardLib->insertOrUpdateOverride($override);
|
||||
if (isError($result)) {
|
||||
http_response_code(500);
|
||||
$this->terminateWithJsonError('override could not be saved');
|
||||
}
|
||||
|
||||
$this->outputJsonSuccess(array('msg' => 'override successfully stored.', 'data' => $override_decoded));
|
||||
}
|
||||
|
||||
public function removeWidgetFromUserOverride()
|
||||
{
|
||||
$input = json_decode($this->input->raw_input_stream);
|
||||
$dashboard_kurzbz = $input->db;
|
||||
$funktion_kurzbz = $input->funktion_kurzbz;
|
||||
$uid = $this->AuthLib->getAuthObj()->username;
|
||||
$widgetid = $input->widgetid;
|
||||
|
||||
$override = $this->DashboardLib->getOverride($dashboard_kurzbz, $uid);
|
||||
if (empty($override)) {
|
||||
http_response_code(404);
|
||||
$this->terminateWithJsonError('userconfig for dashboard ' . $dashboard_kurzbz . ' not found.');
|
||||
}
|
||||
|
||||
$override_decoded = json_decode($override->override, true);
|
||||
|
||||
if (!$this->DashboardLib->removeWidgetFromWidgets($override_decoded, $funktion_kurzbz, $widgetid))
|
||||
{
|
||||
http_response_code(404);
|
||||
$this->terminateWithJsonError('widgetid ' . $widgetid . ' not found');
|
||||
}
|
||||
|
||||
$override->override = json_encode($override_decoded);
|
||||
$result = $this->DashboardLib->insertOrUpdateOverride($override, $uid);
|
||||
if (isError($result))
|
||||
{
|
||||
http_response_code(500);
|
||||
$this->terminateWithJsonError('failed to remove widget');
|
||||
}
|
||||
$this->outputJsonSuccess(array('msg' => 'override successfully updated.'));
|
||||
}
|
||||
|
||||
public function funktionen()
|
||||
{
|
||||
$funktionen = $this->FunktionModel->load();
|
||||
|
||||
if (isError($funktionen)) {
|
||||
http_response_code(404);
|
||||
$this->terminateWithJsonError([
|
||||
'error' => getError($funktionen)
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->outputJsonSuccess(getData($funktionen) ?: []);
|
||||
}
|
||||
|
||||
public function preset()
|
||||
{
|
||||
$db = $this->input->get('db');
|
||||
$funktion = $this->input->get('funktion');
|
||||
|
||||
$conf = $this->DashboardLib->getPreset($db, $funktion);
|
||||
|
||||
if (!$conf)
|
||||
return $this->outputJsonSuccess(['widgets' => [$funktion => []]]);
|
||||
|
||||
return $this->outputJsonSuccess(json_decode($conf->preset, true));
|
||||
}
|
||||
|
||||
public function presetBatch()
|
||||
{
|
||||
$db = $this->input->get('db');
|
||||
$funktionen = $this->input->get('funktionen');
|
||||
$result = [];
|
||||
|
||||
foreach ($funktionen as $funktion) {
|
||||
$conf = $this->DashboardLib->getPreset($db, $funktion);
|
||||
if ($conf)
|
||||
{
|
||||
$preset = json_decode($conf->preset, true);
|
||||
if (!isset($preset[$funktion]) || !isset($preset[$funktion]['widgets']))
|
||||
$result[$funktion] = [];
|
||||
else
|
||||
$result[$funktion] = $preset[$funktion]['widgets'];
|
||||
}
|
||||
else
|
||||
$result[$funktion] = [];
|
||||
}
|
||||
|
||||
return $this->outputJsonSuccess($result);
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
<?php
|
||||
defined('BASEPATH') || exit('No direct script access allowed');
|
||||
/**
|
||||
* Description of Widget
|
||||
*
|
||||
* @author chris
|
||||
*/
|
||||
class Dashboard extends Auth_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
array(
|
||||
'index' => 'dashboard/admin:r',
|
||||
'create' => 'dashboard/admin:rw',
|
||||
'update' => 'dashboard/admin:rw',
|
||||
'delete' => 'dashboard/admin:rw'
|
||||
)
|
||||
);
|
||||
|
||||
$this->load->library('dashboard/DashboardLib', null, 'DashboardLib');
|
||||
$this->load->model('dashboard/Dashboard_model', 'DashboardModel');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$result = $this->DashboardModel->load();
|
||||
|
||||
if (isError($result)) {
|
||||
http_response_code(404);
|
||||
$this->terminateWithJsonError([
|
||||
'error' => getError($result)
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->outputJsonSuccess(getData($result) ?: []);
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
$input = $this->getPostJSON();
|
||||
|
||||
$result = $this->DashboardModel->insert($input);
|
||||
|
||||
if (isError($result)) {
|
||||
http_response_code(404);
|
||||
$this->terminateWithJsonError([
|
||||
'error' => getError($result)
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->outputJsonSuccess(getData($result) ?: []);
|
||||
}
|
||||
|
||||
public function update()
|
||||
{
|
||||
$input = $this->getPostJSON();
|
||||
|
||||
$result = $this->DashboardModel->update($input->dashboard_id, $input);
|
||||
|
||||
if (isError($result)) {
|
||||
http_response_code(404);
|
||||
$this->terminateWithJsonError([
|
||||
'error' => getError($result)
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->outputJsonSuccess(getData($result) ?: []);
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$input = $this->getPostJSON();
|
||||
|
||||
$result = $this->DashboardModel->delete($input->dashboard_id);
|
||||
|
||||
if (isError($result)) {
|
||||
http_response_code(404);
|
||||
$this->terminateWithJsonError([
|
||||
'error' => getError($result)
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->outputJsonSuccess(getData($result) ?: []);
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
*/
|
||||
class DashboardDemo extends Auth_Controller
|
||||
{
|
||||
private $_uid; // uid of the logged user
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// Set required permissions
|
||||
parent::__construct(
|
||||
array(
|
||||
'index' => 'dashboard/benutzer:r',
|
||||
'admin' => 'dashboard/admin:rw'
|
||||
)
|
||||
);
|
||||
|
||||
$this->load->library('AuthLib');
|
||||
$this->load->library('WidgetLib');
|
||||
|
||||
$this->_setAuthUID(); // sets property uid
|
||||
|
||||
$this->setControllerId(); // sets the controller id
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
public function index()
|
||||
{
|
||||
$this->load->view('dashboard/dashboard_demo.php', []);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
public function admin()
|
||||
{
|
||||
$this->load->view('dashboard/dashboard_demo_admin.php', []);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Private methods
|
||||
|
||||
/**
|
||||
* Retrieve the UID of the logged user and checks if it is valid
|
||||
*/
|
||||
private function _setAuthUID()
|
||||
{
|
||||
$this->_uid = getAuthUID();
|
||||
|
||||
if (!$this->_uid) show_error('User authentification failed');
|
||||
}
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
<?php
|
||||
defined('BASEPATH') || exit('No direct script access allowed');
|
||||
/**
|
||||
* Description of Widget
|
||||
*
|
||||
* @author chris
|
||||
*/
|
||||
class Widget extends Auth_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
array(
|
||||
'index' => ['dashboard/benutzer:r', 'dashboard/admin:r'],
|
||||
'getAll' => 'dashboard/admin:r',
|
||||
'getWidgetsForDashboard' => ['dashboard/benutzer:rw', 'dashboard/admin:r'],
|
||||
'setAllowed' => 'dashboard/admin:rw'
|
||||
)
|
||||
);
|
||||
|
||||
$this->load->library('dashboard/DashboardLib', null, 'DashboardLib');
|
||||
$this->load->model('dashboard/Widget_model', 'WidgetModel');
|
||||
$this->load->model('dashboard/Dashboard_Widget_model', 'DashboardWidgetModel');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$widget_id = $this->input->get('id');
|
||||
|
||||
$widget = $this->WidgetModel->load($widget_id);
|
||||
|
||||
if (isError($widget) || !getData($widget))
|
||||
return $this->outputJsonSuccess([
|
||||
"widget_id" => 0,
|
||||
"widget_kurzbz" => "notfound",
|
||||
"arguments" => [
|
||||
"className" => 'alert-danger',
|
||||
"title" => 'Widget Not Found',
|
||||
"msg" => 'The widget with the id ' . $widget_id . ' could not be found'
|
||||
],
|
||||
"setup" => [
|
||||
"name" => 'Widget Not Found',
|
||||
"file" => absoluteJsImportUrl('public/js/components/DashboardWidget/Default.js'),
|
||||
"width" => 1,
|
||||
"height" => 1
|
||||
]
|
||||
]);
|
||||
|
||||
$widget = current(getData($widget));
|
||||
$widget->arguments = json_decode($widget->arguments);
|
||||
$tmpsetup = json_decode($widget->setup);
|
||||
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
|
||||
$widget->setup = $tmpsetup;
|
||||
|
||||
return $this->outputJsonSuccess($widget);
|
||||
}
|
||||
|
||||
public function getAll()
|
||||
{
|
||||
$dashboard_id = $this->input->get('dashboard_id');
|
||||
$result = $this->WidgetModel->getWithAllowedForDashboard($dashboard_id);
|
||||
|
||||
if (isError($result))
|
||||
return $this->outputJsonError(getError($result));
|
||||
|
||||
$tmpwidgets = getData($result) ?: [];
|
||||
$widgets = array_map(function($widget) {
|
||||
$widget->arguments = json_decode($widget->arguments);
|
||||
$tmpsetup = json_decode($widget->setup);
|
||||
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
|
||||
$widget->setup = $tmpsetup;
|
||||
return $widget;
|
||||
}, $tmpwidgets);
|
||||
|
||||
$this->outputJsonSuccess($widgets);
|
||||
}
|
||||
|
||||
public function getWidgetsForDashboard()
|
||||
{
|
||||
$db = $this->input->get('db');
|
||||
$result = $this->WidgetModel->getForDashboard($db);
|
||||
|
||||
if (isError($result)) {
|
||||
http_response_code(404);
|
||||
$this->terminateWithJsonError([
|
||||
'error' => getError($result)
|
||||
]);
|
||||
}
|
||||
|
||||
$tmpwidgets = getData($result) ?: [];
|
||||
$widgets = array_map(function($widget) {
|
||||
$widget->arguments = json_decode($widget->arguments);
|
||||
$tmpsetup = json_decode($widget->setup);
|
||||
$tmpsetup->file = absoluteJsImportUrl($tmpsetup->file);
|
||||
$widget->setup = $tmpsetup;
|
||||
return $widget;
|
||||
}, $tmpwidgets);
|
||||
|
||||
$this->outputJsonSuccess($widgets);
|
||||
}
|
||||
|
||||
public function setAllowed()
|
||||
{
|
||||
$input = $this->getPostJSON();
|
||||
|
||||
$dashboard_id = $input->dashboard_id;
|
||||
$widget_id = $input->widget_id;
|
||||
$action = $input->action;
|
||||
|
||||
if ($action == 'add') {
|
||||
$result = $this->DashboardWidgetModel->insert([
|
||||
'dashboard_id' => $dashboard_id,
|
||||
'widget_id' => $widget_id
|
||||
]);
|
||||
} elseif ($action == 'delete') {
|
||||
$result = $this->DashboardWidgetModel->delete([
|
||||
'dashboard_id' => $dashboard_id,
|
||||
'widget_id' => $widget_id
|
||||
]);
|
||||
} else {
|
||||
http_response_code(404); // TODO(chris): 400?
|
||||
$this->terminateWithJsonError([
|
||||
'error' => 'action value invalid'
|
||||
]);
|
||||
}
|
||||
if (isError($result)) {
|
||||
http_response_code(404);
|
||||
$this->terminateWithJsonError([
|
||||
'error' => getError($result)
|
||||
]);
|
||||
}
|
||||
return $this->outputJsonSuccess(getData($result));
|
||||
}
|
||||
}
|
||||
@@ -495,6 +495,10 @@ class AbgabetoolJob extends JOB_Controller
|
||||
// get all new or changed termine in interval
|
||||
$result = $this->_ci->PaabgabeModel->findAbgabenNewOrUpdatedSince($interval, $relevantTypes);
|
||||
$retval = getData($result);
|
||||
if(!$retval) {
|
||||
$this->_ci->logInfo("Keine Emails an Betreuer über neue oder veränderte Termine versandt");
|
||||
return;
|
||||
}
|
||||
|
||||
// group changed/new abgaben for projektarbeiten
|
||||
$projektarbeiten = [];
|
||||
@@ -557,6 +561,8 @@ class AbgabetoolJob extends JOB_Controller
|
||||
$anredeFillString = $data->anrede == "Herr" ? "r" : "";
|
||||
$fullFormattedNameString = $data->first;
|
||||
|
||||
$relevantCounter = 0; // workaround to check if a betreuer needs to have any notification about relevant
|
||||
// abgaben at all to avoid sending empty emails since we filter on certain conditions
|
||||
forEach($tupelArr as $tupel) {
|
||||
$projektarbeit_id = $tupel[0];
|
||||
$betreuerRow = $tupel[1];
|
||||
@@ -575,6 +581,8 @@ class AbgabetoolJob extends JOB_Controller
|
||||
continue;
|
||||
}
|
||||
|
||||
$relevantCounter++;
|
||||
|
||||
// format the Student Name
|
||||
$s = $relevantAbgaben[0];
|
||||
$nameParts = [];
|
||||
@@ -633,6 +641,11 @@ class AbgabetoolJob extends JOB_Controller
|
||||
// done with building the change list, now send it
|
||||
$betreuerRow = $tupelArr[0][1];
|
||||
|
||||
if($relevantCounter == 0) {
|
||||
$this->_ci->logInfo('No Relevant Abgaben to notify Betreuer PersonID: "'.$betreuerRow->person_id.'".');
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = $this->_ci->config->item('URL_MITARBEITER');
|
||||
$url = CIS_ROOT.$path;
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* Overview on cronjob logs
|
||||
*/
|
||||
class Ferienverwaltung extends Auth_Controller
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
array(
|
||||
'index' => ['basis/ferien:r']
|
||||
)
|
||||
);
|
||||
|
||||
// Loads WidgetLib
|
||||
//$this->load->library('WidgetLib');
|
||||
|
||||
// Loads phrases system
|
||||
$this->loadPhrases(
|
||||
array(
|
||||
'global',
|
||||
'ui'
|
||||
//'ferien'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* Everything has a beginning
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->load->view('lehre/ferienverwaltung.php');
|
||||
}
|
||||
}
|
||||
@@ -417,6 +417,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller
|
||||
$notiz_id = $this->input->post('notiz_id');
|
||||
|
||||
$this->NotizModel->addSelect('campus.tbl_dms_version.*');
|
||||
$this->NotizModel->addSelect($this->NotizModel->escape(base_url('content/notizdokdownload.php?id=')) . ' || public.tbl_notiz_dokument.dms_id AS preview');
|
||||
|
||||
$this->NotizModel->addJoin('public.tbl_notiz_dokument', 'ON (public.tbl_notiz_dokument.notiz_id = public.tbl_notiz.notiz_id)');
|
||||
$this->NotizModel->addJoin('campus.tbl_dms_version', 'ON (public.tbl_notiz_dokument.dms_id = campus.tbl_dms_version.dms_id)');
|
||||
|
||||
@@ -128,7 +128,7 @@ class AntragLib
|
||||
return $this->_ci->StudierendenantragstatusModel->resumeAntraegeForAbmeldungStgl($antrag_id);
|
||||
}
|
||||
// NOTE(chris): get last status that is not pause
|
||||
$this->_ci->StudierendenantragstatusModel->addOrder('insertamum');
|
||||
$this->_ci->StudierendenantragstatusModel->addOrder('insertamum', 'DESC');
|
||||
$this->_ci->StudierendenantragstatusModel->addLimit(1);
|
||||
$result = $this->_ci->StudierendenantragstatusModel->loadWhere([
|
||||
'studierendenantrag_id' => $antrag_id,
|
||||
|
||||
@@ -50,6 +50,7 @@ class PermissionLib
|
||||
const LOGINAS_PERSONIDS_BLACKLIST = 'permission_loginas_personids_blacklist';
|
||||
|
||||
private $_ci; // CI instance
|
||||
private $access_rights; // current users access rights
|
||||
private static $bb; // benutzerberechtigung
|
||||
|
||||
/**
|
||||
@@ -61,6 +62,8 @@ class PermissionLib
|
||||
// Loads CI instance
|
||||
$this->_ci =& get_instance();
|
||||
|
||||
$this->access_rights = null;
|
||||
|
||||
$this->_ci->config->load('permission'); // Loads permission configuration
|
||||
|
||||
// If it's NOT called from command line
|
||||
@@ -69,8 +72,10 @@ class PermissionLib
|
||||
// API Caller rights initialization
|
||||
$authObj = $this->_ci->authlib->getAuthObj();
|
||||
self::$bb = new benutzerberechtigung();
|
||||
if ($authObj)
|
||||
if ($authObj) {
|
||||
self::$bb->getBerechtigungen($authObj->{AuthLib::AO_USERNAME});
|
||||
$this->access_rights = self::$bb->berechtigungen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,6 +345,16 @@ class PermissionLib
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the access rights for the current user
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function getAccessRights()
|
||||
{
|
||||
return $this->access_rights;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Private methods
|
||||
|
||||
|
||||
@@ -382,11 +382,7 @@ class StundenplanLib
|
||||
|
||||
$tz = new DateTimeZone($this->_ci->config->item('timezone'));
|
||||
|
||||
$ferienEvents = $this->_ci->FerienModel->execReadOnlyQuery("
|
||||
SELECT *
|
||||
FROM lehre.tbl_ferien
|
||||
WHERE (bisdatum >= ? AND vondatum < ?) AND (studiengang_kz = 0 OR studiengang_kz = ?)
|
||||
", [$start_date, $end_date, $studiengang_kz]);
|
||||
$ferienEvents = $this->_ci->FerienModel->getByDateRange($start_date, $end_date, $studiengang_kz);
|
||||
|
||||
if (isError($ferienEvents))
|
||||
return $ferienEvents;
|
||||
|
||||
@@ -49,7 +49,7 @@ class DashboardLib
|
||||
|
||||
public function getMergedConfig($dashboard_id, $uid)
|
||||
{
|
||||
$defaultconfig = $this->getDefaultConfig($dashboard_id, $uid);
|
||||
$defaultconfig = $this->getDefaultConfig($dashboard_id);
|
||||
$userconfig = $this->getUserConfig($dashboard_id, $uid);
|
||||
|
||||
$mergedconfig = array_replace_recursive($defaultconfig, $userconfig);
|
||||
@@ -57,14 +57,31 @@ class DashboardLib
|
||||
return $mergedconfig;
|
||||
}
|
||||
|
||||
public function getDefaultConfig($dashboard_id, $uid)
|
||||
public function getDefaultConfig($dashboard_id)
|
||||
{
|
||||
$res_presets = $this->_ci->DashboardPresetModel->getPresets($dashboard_id, $uid);
|
||||
$funktion_kurzbzs = [];
|
||||
$rights = $this->_ci->permissionlib->getAccessRights();
|
||||
if ($rights)
|
||||
$funktion_kurzbzs = array_unique(array_map(function ($right) {
|
||||
return $right->funktion_kurzbz;
|
||||
}, $rights));
|
||||
|
||||
$this->_ci->DashboardPresetModel->db
|
||||
->group_start()
|
||||
->where_in('funktion_kurzbz', $funktion_kurzbzs)
|
||||
->or_where('funktion_kurzbz IS NULL')
|
||||
->group_end();
|
||||
|
||||
$this->_ci->DashboardPresetModel->addOrder('funktion_kurzbz', 'DESC');
|
||||
|
||||
$result = $this->_ci->DashboardPresetModel->loadWhere([
|
||||
'dashboard_id' => $dashboard_id
|
||||
]);
|
||||
$defaultconfig = array();
|
||||
|
||||
if (hasData($res_presets))
|
||||
if (hasData($result))
|
||||
{
|
||||
$presets = getData($res_presets);
|
||||
$presets = getData($result);
|
||||
foreach ($presets as $presetobj)
|
||||
{
|
||||
$preset = json_decode($presetobj->preset, true);
|
||||
@@ -137,8 +154,10 @@ class DashboardLib
|
||||
$dashboard = $this->getDashboardByKurzbz($dashboard_kurzbz);
|
||||
|
||||
$funktion_kurzbz = ($section === self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL) ? null : $section;
|
||||
$result = $this->_ci->DashboardPresetModel
|
||||
->getPresetByDashboardAndFunktion($dashboard->dashboard_id, $funktion_kurzbz);
|
||||
$result = $this->_ci->DashboardPresetModel->loadWhere([
|
||||
'dashboard_id' => $dashboard->dashboard_id,
|
||||
'funktion_kurzbz' => $funktion_kurzbz
|
||||
]);
|
||||
|
||||
if (hasData($result))
|
||||
{
|
||||
@@ -195,11 +214,11 @@ class DashboardLib
|
||||
{
|
||||
foreach ($addwigets as $widget)
|
||||
{
|
||||
if(!isset($widget->widgetid))
|
||||
if(!isset($widget['widgetid']))
|
||||
{
|
||||
$widget->widgetid = $this->generateWidgetId($dashboard_kurzbz);
|
||||
$widget['widgetid'] = $this->generateWidgetId($dashboard_kurzbz);
|
||||
}
|
||||
$this->addWidgetToWidgets($widgets, $section, $widget, $widget->widgetid);
|
||||
$this->addWidgetToWidgets($widgets, $section, $widget, $widget['widgetid']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ namespace vertragsbestandteil;
|
||||
|
||||
use Exception;
|
||||
use vertragsbestandteil\VertragsbestandteilStunden;
|
||||
use vertragsbestandteil\VertragsbestandteilLohnguide;
|
||||
|
||||
/**
|
||||
* Description of VertragsbestandteilFactory
|
||||
@@ -22,6 +23,7 @@ class VertragsbestandteilFactory
|
||||
const VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH = 'urlaubsanspruch';
|
||||
const VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG = 'zeitaufzeichnung';
|
||||
const VERTRAGSBESTANDTEIL_LEHRE = 'lehre';
|
||||
const VERTRAGSBESTANDTEIL_LOHNGUIDE = 'lohnguide';
|
||||
|
||||
public static function getVertragsbestandteil($data, $fromdb=false)
|
||||
{
|
||||
@@ -69,6 +71,11 @@ class VertragsbestandteilFactory
|
||||
$vertragsbestandteil = new VertragsbestandteilZeitaufzeichnung();
|
||||
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
|
||||
break;
|
||||
|
||||
case self::VERTRAGSBESTANDTEIL_LOHNGUIDE:
|
||||
$vertragsbestandteil = new VertragsbestandteilLohnguide();
|
||||
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception('Unknown vertragsbestandteiltyp_kurzbz '
|
||||
@@ -127,6 +134,12 @@ class VertragsbestandteilFactory
|
||||
$vertragsbestandteildbmodel = $CI->VertragsbestandteilZeitaufzeichnung_model;
|
||||
break;
|
||||
|
||||
case self::VERTRAGSBESTANDTEIL_LOHNGUIDE:
|
||||
$CI->load->model('vertragsbestandteil/VertragsbestandteilLohnguide_model',
|
||||
'VertragsbestandteilLohnguide_model');
|
||||
$vertragsbestandteildbmodel = $CI->VertragsbestandteilLohnguide_model;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Exception('Unknown vertragsbestandteil_kurzbz '
|
||||
. $vertragsbestandteil_kurzbz);
|
||||
|
||||
@@ -10,6 +10,7 @@ require_once __DIR__ . '/VertragsbestandteilKuendigungsfrist.php';
|
||||
require_once __DIR__ . '/VertragsbestandteilUrlaubsanspruch.php';
|
||||
require_once __DIR__ . '/VertragsbestandteilFreitext.php';
|
||||
require_once __DIR__ . '/VertragsbestandteilKarenz.php';
|
||||
require_once __DIR__ . '/VertragsbestandteilLohnguide.php';
|
||||
require_once __DIR__ . '/VertragsbestandteilFactory.php';
|
||||
require_once __DIR__ . '/OverlapChecker.php';
|
||||
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
namespace vertragsbestandteil;
|
||||
|
||||
use vertragsbestandteil\Vertragsbestandteil;
|
||||
use vertragsbestandteil\VertragsbestandteilFactory;
|
||||
|
||||
class VertragsbestandteilLohnguide extends Vertragsbestandteil
|
||||
{
|
||||
protected $stellenbezeichnung;
|
||||
protected $vordienstzeit;
|
||||
protected $fachrichtung_kurzbz;
|
||||
protected $modellstelle_kurzbz;
|
||||
protected $kommentar_person;
|
||||
protected $kommentar_modellstelle;
|
||||
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->setVertragsbestandteiltyp_kurzbz(
|
||||
VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_LOHNGUIDE);
|
||||
}
|
||||
|
||||
public function getStellenbezeichnung()
|
||||
{
|
||||
return $this->stellenbezeichnung;
|
||||
}
|
||||
|
||||
public function setStellenbezeichnung($stellenbezeichnung): self
|
||||
{
|
||||
$this->markDirty('stellenbezeichnung', $this->stellenbezeichnung, $stellenbezeichnung);
|
||||
$this->stellenbezeichnung = $stellenbezeichnung;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getVordienstzeit()
|
||||
{
|
||||
return $this->vordienstzeit;
|
||||
}
|
||||
|
||||
public function setVordienstzeit($vordienstzeit): self
|
||||
{
|
||||
$this->markDirty('vordienstzeit', $this->vordienstzeit, $vordienstzeit);
|
||||
$this->vordienstzeit = $vordienstzeit;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFachrichtung_kurzbz()
|
||||
{
|
||||
return $this->fachrichtung_kurzbz;
|
||||
}
|
||||
|
||||
public function setFachrichtung_kurzbz($fachrichtung_kurzbz): self
|
||||
{
|
||||
$this->markDirty('fachrichtung_kurzbz', $this->fachrichtung_kurzbz, $fachrichtung_kurzbz);
|
||||
$this->fachrichtung_kurzbz = $fachrichtung_kurzbz;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getModellstelle_kurzbz()
|
||||
{
|
||||
return $this->modellstelle_kurzbz;
|
||||
}
|
||||
|
||||
public function setModellstelle_kurzbz($modellstelle_kurzbz): self
|
||||
{
|
||||
$this->markDirty('modellstelle_kurzbz', $this->modellstelle_kurzbz, $modellstelle_kurzbz);
|
||||
$this->modellstelle_kurzbz = $modellstelle_kurzbz;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getKommentar_person()
|
||||
{
|
||||
return $this->kommentar_person;
|
||||
}
|
||||
|
||||
public function setKommentar_person($kommentar_person): self
|
||||
{
|
||||
$this->markDirty('kommentar_person', $this->kommentar_person, $kommentar_person);
|
||||
$this->kommentar_person = $kommentar_person;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getKommentar_modellstelle()
|
||||
{
|
||||
return $this->kommentar_modellstelle;
|
||||
}
|
||||
|
||||
public function setKommentar_modellstelle($kommentar_modellstelle): self
|
||||
{
|
||||
$this->markDirty('kommentar_modellstelle', $this->kommentar_modellstelle, $kommentar_modellstelle);
|
||||
$this->kommentar_modellstelle = $kommentar_modellstelle;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function hydrateByStdClass($data, $fromdb=false)
|
||||
{
|
||||
parent::hydrateByStdClass($data, $fromdb);
|
||||
$this->fromdb = $fromdb;
|
||||
isset($data->fachrichtung_kurzbz) && $this->setFachrichtung_kurzbz($data->fachrichtung_kurzbz);
|
||||
isset($data->stellenbezeichnung) && $this->setStellenbezeichnung($data->stellenbezeichnung);
|
||||
isset($data->vordienstzeit) && $this->setVordienstzeit($data->vordienstzeit);
|
||||
isset($data->modellstelle_kurzbz) && $this->setModellstelle_kurzbz($data->modellstelle_kurzbz);
|
||||
isset($data->kommentar_person) && $this->setKommentar_person($data->kommentar_person);
|
||||
isset($data->kommentar_modellstelle) && $this->setKommentar_modellstelle($data->kommentar_modellstelle);
|
||||
$this->fromdb = false;
|
||||
}
|
||||
|
||||
public function toStdClass(): \stdClass
|
||||
{
|
||||
$tmp = array(
|
||||
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
|
||||
'stellenbezeichnung' => $this->getStellenbezeichnung(),
|
||||
'vordienstzeit' => $this->getVordienstzeit(),
|
||||
'fachrichtung_kurzbz' => $this->getFachrichtung_kurzbz(),
|
||||
'modellstelle_kurzbz' => $this->getModellstelle_kurzbz(),
|
||||
'kommentar_person' => $this->getKommentar_person(),
|
||||
'kommentar_modellstelle' => $this->getKommentar_modellstelle(),
|
||||
);
|
||||
|
||||
$tmp = array_filter($tmp, function($k) {
|
||||
return in_array($k, $this->modifiedcolumns);
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
|
||||
return (object) $tmp;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
$txt = <<<EOTXT
|
||||
modellstelle_kurzbz: {$this->getModellstelle_kurzbz()}
|
||||
|
||||
EOTXT;
|
||||
return parent::__toString() . $txt;
|
||||
}
|
||||
|
||||
/* public function validate()
|
||||
{
|
||||
if( !(filter_var($this->tage, FILTER_VALIDATE_INT,
|
||||
array(
|
||||
'options' => array(
|
||||
'min_range' => 1,
|
||||
'max_range' => 50
|
||||
)
|
||||
)
|
||||
)) ) {
|
||||
$this->validationerrors[] = 'Urlaubsanspruch muss eine Tagesanzahl im Bereich 1 bis 50 sein.';
|
||||
}
|
||||
|
||||
return parent::validate();
|
||||
} */
|
||||
}
|
||||
@@ -11,57 +11,4 @@ class Dashboard_Preset_model extends DB_Model
|
||||
$this->dbTable = 'dashboard.tbl_dashboard_preset';
|
||||
$this->pk = 'preset_id';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Presets of given uid.
|
||||
* @param integer dashboard_id
|
||||
* @param string $uid
|
||||
* @return array
|
||||
*/
|
||||
public function getPresets($dashboard_id, $uid)
|
||||
{
|
||||
// TODO: get Funktionen for uid and load all preset for all funktionen for uid
|
||||
//return $this->loadWhere(array('dashboard_id' => $dashboard_id, 'funktion_kurzbz'=> null));
|
||||
$sql = <<<EOSQL
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
dashboard.tbl_dashboard_preset
|
||||
WHERE
|
||||
dashboard_id = ?
|
||||
AND (
|
||||
funktion_kurzbz IN (
|
||||
SELECT
|
||||
DISTINCT funktion_kurzbz
|
||||
FROM
|
||||
public.tbl_benutzerfunktion
|
||||
WHERE
|
||||
uid = ?
|
||||
AND
|
||||
NOW()::date
|
||||
BETWEEN
|
||||
COALESCE(datum_von, '1970-01-01')
|
||||
AND
|
||||
COALESCE(datum_bis, '2170-12-31')
|
||||
)
|
||||
OR
|
||||
funktion_kurzbz IS NULL
|
||||
)
|
||||
ORDER BY
|
||||
funktion_kurzbz DESC
|
||||
EOSQL;
|
||||
|
||||
return $this->execQuery($sql, array($dashboard_id, $uid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Preset by Dashboard and Funktion
|
||||
* @param integer dashboard_id
|
||||
* @param string funktion_kurzbz
|
||||
* @return array
|
||||
*/
|
||||
public function getPresetByDashboardAndFunktion($dashboard_id, $funktion_kurzbz)
|
||||
{
|
||||
return $this->loadWhere(array('dashboard_id' => $dashboard_id, 'funktion_kurzbz' => $funktion_kurzbz));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,14 +402,17 @@ class Lehrveranstaltung_model extends DB_Model
|
||||
SELECT
|
||||
vorname, nachname, mitarbeiter_uid, lehrfunktion_kurzbz
|
||||
FROM
|
||||
lehre.tbl_lehreinheit
|
||||
lehre.tbl_lehreinheit le
|
||||
JOIN lehre.tbl_lehreinheitmitarbeiter lema USING (lehreinheit_id)
|
||||
JOIN public.tbl_benutzer b ON b.uid = lema.mitarbeiter_uid
|
||||
JOIN public.tbl_person p using (person_id)
|
||||
WHERE
|
||||
tbl_lehreinheit.lehrveranstaltung_id= ?
|
||||
AND tbl_lehreinheit.studiensemester_kurzbz = ?
|
||||
le.lehrveranstaltung_id= ?
|
||||
AND le.studiensemester_kurzbz = ?
|
||||
AND lehrfunktion_kurzbz = 'LV-Leitung'
|
||||
AND lema.mitarbeiter_uid NOT like '_Dummy%'
|
||||
AND b.aktiv = TRUE
|
||||
AND p.aktiv = TRUE
|
||||
ORDER BY
|
||||
lema.insertamum DESC
|
||||
LIMIT 1
|
||||
|
||||
@@ -79,10 +79,10 @@ class Paabgabe_model extends DB_Model
|
||||
JOIN public.tbl_benutzer ON (public.tbl_benutzer.uid = student_uid)
|
||||
JOIN public.tbl_person USING (person_id)
|
||||
|
||||
WHERE (campus.tbl_paabgabe.insertamum >= NOW() - INTERVAL ?
|
||||
OR campus.tbl_paabgabe.updateamum >= NOW() - INTERVAL ?)
|
||||
AND campus.tbl_paabgabe.paabgabetyp_kurzbz IN ?";
|
||||
|
||||
WHERE (campus.tbl_paabgabe.insertamum::date = CURRENT_DATE - INTERVAL ?
|
||||
OR campus.tbl_paabgabe.updateamum::date = CURRENT_DATE - INTERVAL ?)
|
||||
AND campus.tbl_paabgabe.paabgabetyp_kurzbz IN ?";
|
||||
|
||||
return $this->execQuery($query, [$interval, $interval, $relevantTypes]);
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ class Paabgabe_model extends DB_Model
|
||||
JOIN public.tbl_person ON (public.tbl_benutzer.person_id = public.tbl_person.person_id)
|
||||
|
||||
WHERE campus.tbl_paabgabe.abgabedatum IS NOT NULL
|
||||
AND campus.tbl_paabgabe.abgabedatum >= NOW() - INTERVAL ?";
|
||||
AND campus.tbl_paabgabe.abgabedatum = CURRENT_DATE - INTERVAL ?";
|
||||
|
||||
if($relevantTypes !== null) {
|
||||
$query .= " AND campus.tbl_paabgabe.paabgabetyp_kurzbz IN ?";
|
||||
|
||||
@@ -9,6 +9,52 @@ class Ferien_model extends DB_Model
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dbTable = 'lehre.tbl_ferien';
|
||||
$this->pk = array('studiengang_kz', 'bezeichnung');
|
||||
$this->pk = 'ferien_id';
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all Ferien between two dates.
|
||||
* @param $vondatum
|
||||
* @param $bisdatum
|
||||
* @param $studiengang_kz by default, loads only Ferien from oe of 0 Studiengang (and parents)
|
||||
* @return object success or error
|
||||
*/
|
||||
public function getByDateRange($vondatum, $bisdatum, $studiengang_kz = 0)
|
||||
{
|
||||
if (!is_numeric($studiengang_kz)) return error("Invalid Studiengang Kz");
|
||||
if (!is_valid_date($vondatum)) return error("Invalid von date");
|
||||
if (!is_valid_date($bisdatum)) return error("Invalid bis date");
|
||||
|
||||
// get oe from studiengang
|
||||
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
|
||||
$result = $this->StudiengangModel->loadWhere(['studiengang_kz' => $studiengang_kz]);
|
||||
|
||||
if (isError($result)) return $result;
|
||||
if (!hasData($result)) return success([]);
|
||||
|
||||
$oe_kurzbz = getData($result)[0]->oe_kurzbz;
|
||||
|
||||
// get all parents oes
|
||||
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
|
||||
$result = $this->OrganisationseinheitModel->getParents($oe_kurzbz);
|
||||
|
||||
if (isError($result)) return $result;
|
||||
if (!hasData($result)) return success([]);
|
||||
|
||||
$parents = array_column(getData($result), 'oe_kurzbz');
|
||||
|
||||
// get ferien - use oe_kurzbz
|
||||
$qry = "
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
lehre.tbl_ferien
|
||||
WHERE
|
||||
bisdatum >= ? AND vondatum < ?
|
||||
AND (oe_kurzbz IS NULL OR oe_kurzbz IN ?)
|
||||
ORDER BY
|
||||
vondatum";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, [$vondatum, $bisdatum, $parents]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
class Ferientyp_model extends DB_Model
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dbTable = 'lehre.tbl_ferientyp';
|
||||
$this->pk = 'ferientyp_kurzbz';
|
||||
$this->hasSequence = false;
|
||||
}
|
||||
}
|
||||
@@ -594,7 +594,10 @@ class Studiengang_model extends DB_Model
|
||||
$this->addSelect('p.prestudent_id');
|
||||
$this->addSelect('pers.vorname');
|
||||
$this->addSelect('pers.nachname');
|
||||
$this->addSelect("CONCAT(UPPER(pers.nachname), ' ', pers.vorname, ' (', " . $this->dbTable . ".bezeichnung, ')') AS name");
|
||||
$this->addSelect("CONCAT(UPPER(pers.nachname), ' ', pers.vorname, ' (', "
|
||||
. $this->dbTable . ".bezeichnung, ', ', "
|
||||
. "UPPER(" . $this->dbTable . ".typ), "
|
||||
. "UPPER(" . $this->dbTable . ".kurzbz),')') AS name");
|
||||
|
||||
$this->addJoin('public.tbl_prestudent p', 'studiengang_kz');
|
||||
$this->addJoin(
|
||||
|
||||
@@ -53,11 +53,9 @@ class Studienjahr_model extends DB_Model
|
||||
* @param int $days
|
||||
* @return array|stdClass|null
|
||||
*/
|
||||
public function getLastOrAktStudienjahr($days = 60)
|
||||
public function getLastOrAktStudienjahr($days = 0)
|
||||
{
|
||||
if (!is_numeric($days)) {
|
||||
$days = 60;
|
||||
}
|
||||
$days = is_numeric($days) ? $this->escape($days) : 0;
|
||||
|
||||
$query = '
|
||||
SELECT *
|
||||
@@ -77,19 +75,25 @@ class Studienjahr_model extends DB_Model
|
||||
* @param int $days
|
||||
* @return array|stdClass|null
|
||||
*/
|
||||
public function getAktOrNextStudienjahr($days = 62)
|
||||
public function getAktOrNextStudienjahr($days = 0)
|
||||
{
|
||||
if (!is_numeric($days)) {
|
||||
$days = 62;
|
||||
}
|
||||
$days = is_numeric($days) ? $this->escape($days) : 0;
|
||||
|
||||
$query = '
|
||||
SELECT *
|
||||
FROM public.tbl_studienjahr
|
||||
JOIN public.tbl_studiensemester using(studienjahr_kurzbz)
|
||||
WHERE start < NOW() + \'' . $days . ' DAYS\'::INTERVAL
|
||||
ORDER by start DESC
|
||||
LIMIT 1
|
||||
SELECT * FROM (
|
||||
SELECT
|
||||
jahr.*, MIN(sem.start) AS beginn, MAX(sem.ende) AS ende
|
||||
FROM
|
||||
public.tbl_studienjahr jahr
|
||||
JOIN public.tbl_studiensemester sem using(studienjahr_kurzbz)
|
||||
GROUP BY
|
||||
studienjahr_kurzbz
|
||||
) jahre
|
||||
WHERE
|
||||
ende >= NOW() + \'' . $days . ' DAYS\'::INTERVAL
|
||||
ORDER BY
|
||||
ende
|
||||
LIMIT 1
|
||||
';
|
||||
|
||||
return $this->execQuery($query);
|
||||
|
||||
@@ -261,6 +261,42 @@ class Benutzerfunktion_model extends DB_Model
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get active Kompetenzfeldleitung bei UID.
|
||||
*
|
||||
* @param $uid
|
||||
* @return array|stdClass|null
|
||||
*/
|
||||
public function getKFLByUID($uid)
|
||||
{
|
||||
$query = '
|
||||
SELECT
|
||||
bf.uid,
|
||||
bf.oe_kurzbz,
|
||||
oe.organisationseinheittyp_kurzbz
|
||||
FROM
|
||||
public.tbl_benutzerfunktion bf
|
||||
JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz)
|
||||
JOIN public.tbl_benutzer b USING (uid)
|
||||
WHERE
|
||||
b.uid = ?
|
||||
AND b.aktiv = TRUE
|
||||
AND funktion_kurzbz = \'Leitung\'
|
||||
AND organisationseinheittyp_kurzbz = \'Kompetenzfeld\'
|
||||
AND (datum_von IS NULL OR datum_von <= now())
|
||||
AND (datum_bis IS NULL OR datum_bis >= now())
|
||||
';
|
||||
|
||||
$parameters_array = array();
|
||||
if (is_string($uid))
|
||||
{
|
||||
$parameters_array[] = $uid;
|
||||
}
|
||||
|
||||
return $this->execQuery($query, $parameters_array);
|
||||
}
|
||||
|
||||
|
||||
public function insertBenutzerfunktion($Json)
|
||||
{
|
||||
unset($Json['benutzerfunktion_id']);
|
||||
|
||||
@@ -242,6 +242,7 @@ class Message_model extends DB_Model
|
||||
*/
|
||||
public function getMessagesForTable($person_id, $offset, $limit)
|
||||
{
|
||||
$limitoffset = (!is_null($offset) && !is_null($limit)) ? 'limit ? offset ?' : '';
|
||||
$sql = <<<EOSQL
|
||||
with filtered_messages as (
|
||||
select
|
||||
@@ -310,11 +311,12 @@ class Message_model extends DB_Model
|
||||
public.tbl_person pr on pr.person_id = fm.recipient_id
|
||||
order by
|
||||
m.insertamum DESC
|
||||
limit ?
|
||||
offset ?;
|
||||
{$limitoffset}
|
||||
EOSQL;
|
||||
|
||||
$parametersArray = array($person_id, $person_id, $limit, $offset);
|
||||
$parametersArray = $limitoffset
|
||||
? array($person_id, $person_id, $limit, $offset)
|
||||
: array($person_id, $person_id);
|
||||
|
||||
$count = 0;
|
||||
$data = $this->execQuery($sql, $parametersArray);
|
||||
@@ -325,7 +327,7 @@ EOSQL;
|
||||
$data = getData($data);
|
||||
if($data)
|
||||
{
|
||||
$count = ceil($data[0]->total_msgs / $limit);
|
||||
$count = is_null($limit) ? 1 : ceil($data[0]->total_msgs / $limit);
|
||||
}
|
||||
|
||||
return success(['data' => $data, 'count' => $count]);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
class VertragsbestandteilLohnguide_model extends DB_Model
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dbTable = 'hr.tbl_vertragsbestandteil_lohnguide';
|
||||
$this->pk = 'vertragsbestandteil_id';
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,8 @@ class Vertragsbestandteil_model extends DB_Model
|
||||
kf.arbeitgeber_frist, kf.arbeitnehmer_frist,
|
||||
s.wochenstunden, s.teilzeittyp_kurzbz,
|
||||
u.tage,
|
||||
z.zeitaufzeichnung, z.azgrelevant, z.homeoffice
|
||||
z.zeitaufzeichnung, z.azgrelevant, z.homeoffice,
|
||||
lg.stellenbezeichnung, lg.vordienstzeit, lg.fachrichtung_kurzbz, lg.modellstelle_kurzbz, lg.kommentar_person, lg.kommentar_modellstelle
|
||||
FROM
|
||||
hr.tbl_vertragsbestandteil v
|
||||
LEFT JOIN
|
||||
@@ -63,6 +64,8 @@ class Vertragsbestandteil_model extends DB_Model
|
||||
hr.tbl_vertragsbestandteil_urlaubsanspruch u USING(vertragsbestandteil_id)
|
||||
LEFT JOIN
|
||||
hr.tbl_vertragsbestandteil_zeitaufzeichnung z USING(vertragsbestandteil_id)
|
||||
LEFT JOIN
|
||||
hr.tbl_vertragsbestandteil_lohnguide lg USING(vertragsbestandteil_id)
|
||||
EOSQL;
|
||||
return $sql;
|
||||
}
|
||||
|
||||
+9
-3
@@ -8,9 +8,15 @@ $this->load->view(
|
||||
'axios027' => true,
|
||||
'restclient' => true,
|
||||
'vue3' => true,
|
||||
'customJSModules' => ['public/js/apps/Dashboard.js'],
|
||||
'primevue3' => true,
|
||||
'vuedatepicker11' => true,
|
||||
'customJSs' => [
|
||||
'vendor/moment/luxonjs/luxon.min.js'
|
||||
],
|
||||
'customJSModules' => ['public/js/apps/Dashboard/Admin.js'],
|
||||
'customCSSs' => [
|
||||
'public/css/components/dashboard.css'
|
||||
'public/css/components/dashboard.css',
|
||||
'public/css/components/primevue.css',
|
||||
],
|
||||
'navigationcomponent' => true
|
||||
)
|
||||
@@ -25,7 +31,7 @@ $this->load->view(
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">Dashboard</h1>
|
||||
</div>
|
||||
<core-dashboard dashboard="CIS" apiurl="<?= site_url('dashboard'); ?>"></core-dashboard>
|
||||
<dashboard-admin></dashboard-admin>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
+8
-3
@@ -8,7 +8,12 @@ $this->load->view(
|
||||
'axios027' => true,
|
||||
'restclient' => true,
|
||||
'vue3' => true,
|
||||
'customJSModules' => ['public/js/apps/DashboardAdmin.js'],
|
||||
'vuedatepicker11' => true,
|
||||
'primevue3' => true,
|
||||
'customJSs' => [
|
||||
'vendor/moment/luxonjs/luxon.min.js'
|
||||
],
|
||||
'customJSModules' => ['public/js/apps/Dashboard/Preview.js'],
|
||||
'customCSSs' => [
|
||||
'public/css/components/dashboard.css'
|
||||
],
|
||||
@@ -23,9 +28,9 @@ $this->load->view(
|
||||
|
||||
<div id="content">
|
||||
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
|
||||
<h1 class="h2">Dashboard</h1>
|
||||
<h1 class="h2">Dashboard <?= $dashboard_kurzbz ?></h1>
|
||||
</div>
|
||||
<dashboard-admin dashboard="CIS" apiurl="<?= site_url('dashboard'); ?>"></dashboard-admin>
|
||||
<core-dashboard dashboard="<?= $dashboard_kurzbz ?>"></core-dashboard>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
$includesArray = array(
|
||||
'title' => 'Ferienverwaltung',
|
||||
'axios027' => true,
|
||||
'bootstrap5' => true,
|
||||
'fontawesome6' => true,
|
||||
'vue3' => true,
|
||||
'filtercomponent' => true,
|
||||
'navigationcomponent' => true,
|
||||
'tabulator6' => true,
|
||||
'primevue3' => true,
|
||||
//'vuedatepicker11' => true,
|
||||
'customJSModules' => array('public/js/apps/lehre/Ferienverwaltung/Ferienverwaltung.js'),
|
||||
'customCSSs' => array('vendor/vuejs/vuedatepicker_css/main.css')
|
||||
);
|
||||
|
||||
$this->load->view('templates/FHC-Header', $includesArray);
|
||||
?>
|
||||
|
||||
<div id="main">
|
||||
<div>
|
||||
<ferienverwaltung></ferienverwaltung>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php $this->load->view('templates/FHC-Footer', $includesArray); ?>
|
||||
|
||||
@@ -46,12 +46,13 @@ echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<link rel="stylesheet" href="../../../skin/tablesort.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="../../../skin/style.css.php" type="text/css">
|
||||
<link rel="stylesheet" type="text/css" href="../../../skin/jquery-ui-1.9.2.custom.min.css">
|
||||
<script type="text/javascript" src="../../../vendor/jquery/jquery1/jquery-1.12.4.min.js"></script>
|
||||
<script type="text/javascript" src="../../../vendor/christianbach/tablesorter/jquery.tablesorter.min.js"></script>
|
||||
<script type="text/javascript" src="../../../vendor/components/jqueryui/jquery-ui.min.js"></script>
|
||||
<script type="text/javascript" src="../../../include/js/jquery.ui.datepicker.translation.js"></script>
|
||||
<script type="text/javascript" src="../../../vendor/jquery/sizzle/sizzle.js"></script>';
|
||||
|
||||
include('../../../include/meta/jquery.php');
|
||||
include('../../../include/meta/jquery-tablesorter.php');
|
||||
|
||||
const MOODLE_ADDON_KURZBZ = 'moodle';
|
||||
|
||||
// Load Addons to get Moodle_Path
|
||||
@@ -71,7 +72,7 @@ echo '
|
||||
$("#myTable").tablesorter(
|
||||
{
|
||||
sortList: [[0,0],[1,0]],
|
||||
widgets: [\'zebra\']
|
||||
widgets: [\'zebra\',\'filter\']
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -151,8 +152,9 @@ foreach($service->result as $row)
|
||||
$person = new person();
|
||||
$person->getPersonFromBenutzer($row->operativ_uid);
|
||||
$operativ = $person->nachname.' '.$person->vorname;
|
||||
$oeBez = new organisationseinheit($row->oe_kurzbz);
|
||||
echo '<tr>';
|
||||
echo '<td>',$row->oe_kurzbz,'</td>';
|
||||
echo '<td>',$oeBez->bezeichnung,'</td>';
|
||||
echo '<td><b>'.$row->bezeichnung.'</b></td>';
|
||||
echo '<td>',$row->beschreibung,'</td>';
|
||||
echo '<td><nobr><a href="../profile/index.php?uid='.$row->design_uid.'">',$design,'</a></nobr></td>';
|
||||
|
||||
@@ -293,7 +293,7 @@ else if (isset($_SESSION['pruefling_id']))
|
||||
}
|
||||
$lastsemester = $row->semester;
|
||||
|
||||
echo '<table border="0" cellspacing="0" cellpadding="0" id="Gebiet" style="display: visible; border-collapse: separate; border-spacing: 0 3px;">';
|
||||
echo '<table border="0" cellspacing="0" cellpadding="0" id="Gebiet" style="display: visible; border-collapse: separate; border-spacing: 0 3px; margin-top: 5px;">';
|
||||
echo '<tr><td class="HeaderTesttool">'. ($row->semester == '1' ? $p->t('testtool/basisgebiete') : $p->t('testtool/quereinstiegsgebiete')).'</td></tr>';
|
||||
}
|
||||
|
||||
|
||||
@@ -342,6 +342,8 @@ echo '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
|
||||
<vbox>
|
||||
<checkbox id="mitarbeiter-entwicklungsteam-detail-checkbox-neu" checked="true" hidden="true" />
|
||||
<textbox id="mitarbeiter-entwicklungsteam-detail-textbox-studiengang" hidden="true" />
|
||||
<textbox id="mitarbeiter-entwicklungsteam-detail-entwicklungsteam_id" hidden="true" />
|
||||
|
||||
<groupbox id="mitarbeiter-entwicklungsteam-detail-groupbox" flex="1">
|
||||
<caption label="Details" />
|
||||
<grid id="mitarbeiter-entwicklungsteam-detail-grid" style="margin:4px;" flex="1">
|
||||
|
||||
@@ -1708,6 +1708,7 @@ function MitarbeiterEntwicklungsteamSelect()
|
||||
document.getElementById('mitarbeiter-entwicklungsteam-detail-textbox-studiengang').value=studiengang_kz;
|
||||
document.getElementById('mitarbeiter-entwicklungsteam-detail-datum-beginn').value=beginn;
|
||||
document.getElementById('mitarbeiter-entwicklungsteam-detail-datum-ende').value=ende;
|
||||
document.getElementById('mitarbeiter-entwicklungsteam-detail-entwicklungsteam_id').value=entwicklungsteam_id;
|
||||
MitarbeiterEntwicklungsteamDetailDisableFields(false);
|
||||
}
|
||||
|
||||
@@ -1725,6 +1726,7 @@ function MitarbeiterEntwicklungsteamSpeichern()
|
||||
studiengang_kz_old = document.getElementById('mitarbeiter-entwicklungsteam-detail-textbox-studiengang').value;
|
||||
beginn = document.getElementById('mitarbeiter-entwicklungsteam-detail-datum-beginn').value;
|
||||
ende = document.getElementById('mitarbeiter-entwicklungsteam-detail-datum-ende').value;
|
||||
entwicklungsteam_id = document.getElementById('mitarbeiter-entwicklungsteam-detail-entwicklungsteam_id').value;
|
||||
|
||||
if(studiengang_kz=='')
|
||||
{
|
||||
|
||||
@@ -802,6 +802,10 @@ echo '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
|
||||
class="sortDirectionIndicator"
|
||||
sort="rdf:http://www.technikum-wien.at/prestudentrolle/rdf#fgm" />
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="student-prestudent-tree-rolle-faktiv" label="F-Aktiv" flex="1" hidden="true" persist="hidden, width, ordinal"
|
||||
class="sortDirectionIndicator"
|
||||
sort="rdf:http://www.technikum-wien.at/prestudentrolle/rdf#faktiv" />
|
||||
<splitter class="tree-splitter"/>
|
||||
</treecols>
|
||||
|
||||
<template>
|
||||
@@ -828,6 +832,7 @@ echo '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
|
||||
<treecell properties="Aktiv_rdf:http://www.technikum-wien.at/prestudentrolle/rdf#aktiv rdf:http://www.technikum-wien.at/prestudentrolle/rdf#stichtagsaktiv" label="rdf:http://www.technikum-wien.at/prestudentrolle/rdf#updateamum"/>
|
||||
<treecell properties="Aktiv_rdf:http://www.technikum-wien.at/prestudentrolle/rdf#aktiv rdf:http://www.technikum-wien.at/prestudentrolle/rdf#stichtagsaktiv" label="rdf:http://www.technikum-wien.at/prestudentrolle/rdf#updatevon"/>
|
||||
<treecell properties="Aktiv_rdf:http://www.technikum-wien.at/prestudentrolle/rdf#aktiv rdf:http://www.technikum-wien.at/prestudentrolle/rdf#stichtagsaktiv" label="rdf:http://www.technikum-wien.at/prestudentrolle/rdf#fgm"/>
|
||||
<treecell properties="Aktiv_rdf:http://www.technikum-wien.at/prestudentrolle/rdf#aktiv rdf:http://www.technikum-wien.at/prestudentrolle/rdf#stichtagsaktiv" label="rdf:http://www.technikum-wien.at/prestudentrolle/rdf#faktiv"/>
|
||||
</treerow>
|
||||
</treeitem>
|
||||
</treechildren>
|
||||
|
||||
@@ -3550,9 +3550,19 @@ function StudentZeugnisDokumentArchivieren()
|
||||
case 'microcredentialzertifikat_1':
|
||||
case 'microcredentialzertifikat_2':
|
||||
case 'microcredentialzertifikat_3':
|
||||
case 'microcredentialzertifikat_4':
|
||||
case 'microcredential_1':
|
||||
case 'microcredential_2':
|
||||
case 'microcredential_3':
|
||||
case 'microcredential_4':
|
||||
case 'microdegree_1':
|
||||
case 'microdegree_2':
|
||||
case 'microdegree_3':
|
||||
case 'microdegree_4':
|
||||
case 'microdegreeabschluss_1':
|
||||
case 'microdegreeabschluss_2':
|
||||
case 'microdegreeabschluss_3':
|
||||
case 'microdegreeabschluss_4':
|
||||
xml = 'microcredential.xml.php';
|
||||
break;
|
||||
|
||||
|
||||
@@ -364,9 +364,10 @@ class entwicklungsteam extends basis_db
|
||||
$bismeldung_jahr = $datetime->format('Y');
|
||||
|
||||
//laden des Datensatzes
|
||||
$qry = "SELECT *
|
||||
$qry = "SELECT tbl_entwicklungsteam.*, tbl_besqual.*, tbl_studiengang.studiengang_kz, tbl_studiengang.melderelevant
|
||||
FROM bis.tbl_entwicklungsteam
|
||||
JOIN bis.tbl_besqual USING(besqualcode)
|
||||
JOIN public.tbl_studiengang USING(studiengang_kz)
|
||||
WHERE mitarbeiter_uid=".$this->db_add_param($mitarbeiter_uid)."
|
||||
AND (beginn is NULL OR beginn <= make_date(". $this->db_add_param($bismeldung_jahr). "::INTEGER, 12, 31))
|
||||
AND (ende is NULL OR ende >= make_date(". $this->db_add_param($bismeldung_jahr). "::INTEGER, 1, 1))";
|
||||
@@ -394,6 +395,7 @@ class entwicklungsteam extends basis_db
|
||||
$obj->insertvon = $row->insertvon;
|
||||
$obj->ext_id = $row->ext_id;
|
||||
$obj->besqual = $row->besqualbez;
|
||||
$obj->melderelevant = $this->db_parse_bool($row->melderelevant);
|
||||
|
||||
$this->result[] = $obj;
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
* @create 07-12-2006
|
||||
*/
|
||||
require_once(dirname(__FILE__).'/basis_db.class.php');
|
||||
require_once(dirname(__FILE__).'/organisationseinheit.class.php');
|
||||
|
||||
class ferien extends basis_db
|
||||
{
|
||||
@@ -62,8 +63,50 @@ class ferien extends basis_db
|
||||
$this->errormsg = 'Studiengang_kz ist ungültig';
|
||||
return false;
|
||||
}
|
||||
|
||||
// get oe from studiengang
|
||||
$sql_query="
|
||||
SELECT
|
||||
oe_kurzbz
|
||||
FROM
|
||||
public.tbl_studiengang
|
||||
WHERE
|
||||
studiengang_kz=".$this->db_add_param($stg_kz, FHC_INTEGER)."
|
||||
ORDER BY
|
||||
studiengang_kz";
|
||||
|
||||
$sql_query="SELECT * FROM lehre.tbl_ferien WHERE studiengang_kz=0 OR studiengang_kz=".$this->db_add_param($stg_kz, FHC_INTEGER)." ORDER BY vondatum;";
|
||||
if (!$this->db_query($sql_query))
|
||||
{
|
||||
$this->errormsg = $this->db_last_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
$oe_kurzbz = '';
|
||||
while ($row = $this->db_fetch_object())
|
||||
{
|
||||
$oe_kurzbz = $row->oe_kurzbz;
|
||||
}
|
||||
|
||||
// get all parents oes
|
||||
$organisationseinheit = new organisationseinheit();
|
||||
$parents = $organisationseinheit->getParents($oe_kurzbz);
|
||||
|
||||
if (!$parents)
|
||||
{
|
||||
$this->errormsg = $parents->errormsg;
|
||||
return false;
|
||||
}
|
||||
|
||||
$sql_query="
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
lehre.tbl_ferien
|
||||
WHERE
|
||||
oe_kurzbz IS NULL
|
||||
OR oe_kurzbz IN (".$this->implode4SQL($parents).")
|
||||
ORDER BY
|
||||
vondatum";
|
||||
|
||||
if (!$this->db_query($sql_query))
|
||||
{
|
||||
|
||||
+49
-1
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
require_once(dirname(__FILE__).'/basis_db.class.php');
|
||||
require_once(dirname(__FILE__).'/'.EXT_FKT_PATH.'/generateZahlungsreferenz.inc.php');
|
||||
require_once(dirname(__FILE__).'/variable.class.php');
|
||||
|
||||
class konto extends basis_db
|
||||
{
|
||||
@@ -432,6 +433,8 @@ class konto extends basis_db
|
||||
|
||||
$qry.=" ORDER BY beschreibung";
|
||||
|
||||
$oehBeitrag = $this->_getOEHBeitrag();
|
||||
|
||||
if($this->db_query($qry))
|
||||
{
|
||||
while($row = $this->db_fetch_object())
|
||||
@@ -440,7 +443,15 @@ class konto extends basis_db
|
||||
|
||||
$typ->buchungstyp_kurzbz = $row->buchungstyp_kurzbz;
|
||||
$typ->beschreibung = $row->beschreibung;
|
||||
$typ->standardbetrag = $row->standardbetrag;
|
||||
if (strtolower($typ->buchungstyp_kurzbz) === 'oeh' && $oehBeitrag)
|
||||
{
|
||||
$typ->standardbetrag = $oehBeitrag;
|
||||
}
|
||||
else
|
||||
{
|
||||
$typ->standardbetrag = $row->standardbetrag;
|
||||
}
|
||||
|
||||
$typ->standardtext = $row->standardtext;
|
||||
$typ->credit_points = $row->credit_points;
|
||||
$typ->aktiv = $this->db_parse_bool($row->aktiv);
|
||||
@@ -990,6 +1001,43 @@ class konto extends basis_db
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private function _getOEHBeitrag()
|
||||
{
|
||||
if(!is_user_logged_in())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$variablen_obj = new variable();
|
||||
$variablen_obj->loadVariables(get_uid());
|
||||
|
||||
$qry = "WITH semstart AS (
|
||||
SELECT start FROM public.tbl_studiensemester
|
||||
WHERE studiensemester_kurzbz = '". $this->db_escape($variablen_obj->variable->semester_aktuell) . "'
|
||||
)
|
||||
SELECT * FROM bis.tbl_oehbeitrag oehb
|
||||
JOIN public.tbl_studiensemester semvon ON oehb.von_studiensemester_kurzbz = semvon.studiensemester_kurzbz
|
||||
LEFT JOIN public.tbl_studiensemester sembis ON oehb.bis_studiensemester_kurzbz = sembis.studiensemester_kurzbz
|
||||
JOIN semstart ON semstart.start::date >= semvon.start::date AND (sembis.studiensemester_kurzbz IS NULL OR semstart.start::date <= sembis.start::date)
|
||||
ORDER BY semvon.start
|
||||
LIMIT 1";
|
||||
|
||||
if ($this->db_query($qry))
|
||||
{
|
||||
if($row = $this->db_fetch_object())
|
||||
{
|
||||
$summe = ($row->studierendenbeitrag + $row->versicherung) * -1;
|
||||
return number_format((float)$summe, 2, '.', '');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->errormsg = 'Fehler bei der Abfrage aufgetreten';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -552,9 +552,41 @@ class lehreinheitmitarbeiter extends basis_db
|
||||
$beginn = new DateTime($beginn);
|
||||
$ende = new DateTime($ende);
|
||||
|
||||
// get relevant Studiensemester
|
||||
$studiensemester_kurzbz_arr = [];
|
||||
|
||||
$qry = '
|
||||
SELECT
|
||||
studiensemester_kurzbz
|
||||
FROM
|
||||
public.tbl_studiensemester
|
||||
WHERE
|
||||
start BETWEEN
|
||||
'. $this->db_add_param($beginn->format('Y-m-d')). ' AND
|
||||
'. $this->db_add_param($ende->format('Y-m-d'));
|
||||
|
||||
if ($this->db_query($qry))
|
||||
{
|
||||
while($row = $this->db_fetch_object())
|
||||
{
|
||||
$studiensemester_kurzbz_arr[] = $row->studiensemester_kurzbz;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->errormsg = 'Fehler bei der Datenbankabfrage';
|
||||
return false;
|
||||
}
|
||||
|
||||
$lehrgaengeDistr = $this->_getLehrgaengeForDistribution($studiensemester_kurzbz_arr);
|
||||
|
||||
if (!is_array($studiensemester_kurzbz_arr) || empty($studiensemester_kurzbz_arr)) return true;
|
||||
|
||||
$qry = '
|
||||
WITH semester_sws_tbl AS (
|
||||
SELECT DISTINCT lehreinheit_id, studiensemester_kurzbz, lema.semesterstunden, stg.studiengang_kz
|
||||
SELECT
|
||||
DISTINCT lehreinheit_id, studiensemester_kurzbz, lema.semesterstunden,
|
||||
stg.studiengang_kz, stg.melde_studiengang_kz, stg.lgartcode, stg.melderelevant
|
||||
FROM lehre.tbl_lehreinheitmitarbeiter lema
|
||||
JOIN lehre.tbl_lehreinheit USING (lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
|
||||
@@ -564,38 +596,104 @@ class lehreinheitmitarbeiter extends basis_db
|
||||
JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz
|
||||
JOIN public.tbl_studiensemester ss USING (studiensemester_kurzbz)
|
||||
WHERE mitarbeiter_uid = '. $this->db_add_param($uid). '
|
||||
AND (
|
||||
ss.start BETWEEN
|
||||
'. $this->db_add_param($beginn->format('Y-m-d')). ' AND
|
||||
'. $this->db_add_param($ende->format('Y-m-d')). ')
|
||||
AND ss.studiensemester_kurzbz IN ('.$this->implode4SQL($studiensemester_kurzbz_arr).')
|
||||
-- nur lehre, die bisgemeldet wird
|
||||
AND lema.bismelden
|
||||
AND stg.melderelevant
|
||||
-- keine lehreinheiten ohne semesterstunden
|
||||
AND lema.semesterstunden != 0
|
||||
AND lema.semesterstunden != 0
|
||||
)
|
||||
|
||||
SELECT
|
||||
studiengang_kz,
|
||||
studiensemester_kurzbz,
|
||||
melde_studiengang_kz,
|
||||
lgartcode,
|
||||
sum(semesterstunden) AS summe,
|
||||
round(sum(semesterstunden) / 15, 2) AS sws
|
||||
FROM
|
||||
semester_sws_tbl
|
||||
GROUP BY
|
||||
studiengang_kz,
|
||||
studiensemester_kurzbz
|
||||
studiensemester_kurzbz,
|
||||
melde_studiengang_kz,
|
||||
lgartcode
|
||||
ORDER BY
|
||||
studiengang_kz;
|
||||
';
|
||||
|
||||
if ($this->db_query($qry))
|
||||
{
|
||||
$additionalLehrgaenge = [];
|
||||
|
||||
while($row = $this->db_fetch_object())
|
||||
{
|
||||
$obj = new StdClass();
|
||||
$obj->studiengang_kz = $row->studiengang_kz;
|
||||
$obj->studiensemester_kurzbz = $row->studiensemester_kurzbz;
|
||||
$obj->melde_studiengang_kz = $row->melde_studiengang_kz;
|
||||
$obj->lgartcode = $row->lgartcode;
|
||||
$obj->sws = $row->sws;
|
||||
|
||||
if (isset($lehrgaengeDistr[$uid][$row->studiensemester_kurzbz]))
|
||||
{
|
||||
$lehrgaenge = $lehrgaengeDistr[$uid][$row->studiensemester_kurzbz];
|
||||
|
||||
foreach ($lehrgaenge as $lehreinheit_id => $lehrgangKzArr)
|
||||
{
|
||||
// wenn lehrgang gefunden, zusammenhängende Lehrgaenge holen und sws aufteilen
|
||||
if (array_key_exists($row->studiengang_kz, $lehrgangKzArr))
|
||||
{
|
||||
foreach ($lehrgangKzArr as $studiengang_kz => $lehrgang)
|
||||
{
|
||||
// check: nur eine Studiengangsverknüpfung pro Mitarbeiter, Semester, und Referenzstudiengang
|
||||
if (
|
||||
$studiengang_kz == $row->studiengang_kz
|
||||
|| isset(
|
||||
$additionalLehrgaenge[$uid][$row->studiensemester_kurzbz][$row->studiengang_kz][$studiengang_kz]
|
||||
)
|
||||
) continue;
|
||||
|
||||
// Lehrgang erstellen
|
||||
$lg = new StdClass();
|
||||
$lg->mitarbeiter_uid = $uid;
|
||||
$lg->melde_studiengang_kz = $lehrgang->melde_studiengang_kz;
|
||||
$lg->lgartcode = $lehrgang->lgartcode;
|
||||
$lg->studiengang_kz = $lehrgang->studiengang_kz;
|
||||
$lg->studiensemester_kurzbz = $lehrgang->studiensemester_kurzbz;
|
||||
$lg->summe = $row->summe;
|
||||
$lg->sws = $row->sws;
|
||||
// Lehrgang, der mit Ursprungsstudiengang aufgrund lehreinheit "verknüpft" ist, hinzufügen
|
||||
$additionalLehrgaenge[$uid][$row->studiensemester_kurzbz][$row->studiengang_kz][$studiengang_kz] = $lg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ignorieren, wenn für den Studiengang keine verknüpften Lehrgaenge hat
|
||||
if (isset($additionalLehrgaenge[$uid][$row->studiensemester_kurzbz][$row->studiengang_kz]))
|
||||
{
|
||||
$addLehrgaenge = $additionalLehrgaenge[$uid][$row->studiensemester_kurzbz][$row->studiengang_kz];
|
||||
|
||||
// sws Durchschnitt über alle verknuepften Lehrgaenge berechnet
|
||||
$summeSws = $row->summe/(count($addLehrgaenge) + 1);
|
||||
$sws = $row->sws/(count($addLehrgaenge) + 1);
|
||||
|
||||
// neue sws zuweisen
|
||||
$obj->summe = $summeSws;
|
||||
$obj->sws = $sws;
|
||||
|
||||
foreach ($addLehrgaenge as $conn_ws_studiengang_kz => $lehrgang)
|
||||
{
|
||||
// sws fuer jeden verknuepften Lehrgang zuweisen
|
||||
$lehrgang->summe = $summeSws;
|
||||
$lehrgang->sws = $sws;
|
||||
|
||||
// neue lehrgang sws hinzufuegen
|
||||
$this->result [] = $lehrgang;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->result []= $obj;
|
||||
}
|
||||
return true;
|
||||
@@ -655,4 +753,63 @@ class lehreinheitmitarbeiter extends basis_db
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get "connected" Lehrgaenge for equal sws distribution.
|
||||
* @param $studiensemester_kurzbz_arr all semester for which Lehrgaenge should be retrieved
|
||||
* @return object success or error
|
||||
*/
|
||||
private function _getLehrgaengeForDistribution($studiensemester_kurzbz_arr)
|
||||
{
|
||||
if (!is_array($studiensemester_kurzbz_arr) || empty($studiensemester_kurzbz_arr)) return [];
|
||||
|
||||
$qry = "
|
||||
WITH gruppen AS (
|
||||
SELECT
|
||||
mitarbeiter_uid, lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, sem.start, sem.ende,
|
||||
lehreinheitgruppe_id, studiengang_kz, melde_studiengang_kz, lgartcode
|
||||
FROM
|
||||
lehre.tbl_lehreinheitmitarbeiter lema
|
||||
JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id)
|
||||
JOIN lehre.tbl_lehreinheitgruppe legr USING (lehreinheit_id)
|
||||
JOIN public.tbl_studiengang stg USING (studiengang_kz)
|
||||
JOIN public.tbl_studiensemester sem USING (studiensemester_kurzbz)
|
||||
WHERE
|
||||
bismelden
|
||||
AND stg.melderelevant
|
||||
AND stg.typ = 'l'
|
||||
AND le.studiensemester_kurzbz IN (".$this->implode4SQL($studiensemester_kurzbz_arr).")
|
||||
)
|
||||
SELECT
|
||||
DISTINCT mitarbeiter_uid, studiensemester_kurzbz, lehreinheit_id, studiengang_kz, melde_studiengang_kz, lgartcode
|
||||
FROM
|
||||
gruppen gr
|
||||
GROUP BY
|
||||
mitarbeiter_uid, studiensemester_kurzbz, lehreinheit_id, studiengang_kz, melde_studiengang_kz, lgartcode
|
||||
ORDER BY
|
||||
mitarbeiter_uid, studiensemester_kurzbz, lehreinheit_id, studiengang_kz, melde_studiengang_kz, lgartcode";
|
||||
|
||||
$lehrgaengeDistributions = [];
|
||||
|
||||
if($this->db_query($qry))
|
||||
{
|
||||
while($row = $this->db_fetch_object())
|
||||
{
|
||||
// group by properties
|
||||
$lehrgaengeDistributions
|
||||
[$row->mitarbeiter_uid]
|
||||
[$row->studiensemester_kurzbz]
|
||||
[$row->lehreinheit_id]
|
||||
[$row->studiengang_kz]
|
||||
= $row;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->errormsg = 'Fehler bei der Datenbankabfrage';
|
||||
return false;
|
||||
}
|
||||
|
||||
return $lehrgaengeDistributions;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -270,6 +270,8 @@ class LehreListHelper
|
||||
} else if ($row->bisio_id != '' && $row->status != 'Incoming' && ($row->von > $stsemdatumvon || $row->von == '')) {
|
||||
// if bis datum is not yet known but von is available already
|
||||
$zusatz .= '(o)(ab '.$datum->formatDatum($row->von, 'd.m.Y').')';
|
||||
} else if ($row->bisio_id != '' && $row->status != 'Incoming' && ($row->von <= $stsemdatumvon || $row->von == '') && ($row->bis == '' || $row->bis > date('Y-m-d'))){
|
||||
$zusatz .= '(o)(ab '.$datum->formatDatum($row->von, 'd.m.Y').')';
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -706,6 +706,7 @@ class prestudent extends person
|
||||
$rolle->bestaetigtam = $row->bestaetigtam;
|
||||
$rolle->bestaetigtvon = $row->bestaetigtvon;
|
||||
$rolle->fgm = $row->fgm;
|
||||
$rolle->faktiv = $this->db_parse_bool($row->faktiv);
|
||||
$rolle->anmerkung_status = $row->anmerkung;
|
||||
$rolle->bewerbung_abgeschicktamum = $row->bewerbung_abgeschicktamum;
|
||||
$rolle->rt_stufe = $row->rt_stufe;
|
||||
|
||||
@@ -197,10 +197,6 @@ html.fs_huge {
|
||||
margin-bottom: -1px;
|
||||
}
|
||||
|
||||
.tiny-90 div.tox.tox-tinymce {
|
||||
height: 90% !important;
|
||||
}
|
||||
|
||||
/* slim begin */
|
||||
.stv .form-label {
|
||||
margin-bottom: .15rem;
|
||||
|
||||
@@ -193,3 +193,6 @@
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.news-list-item p {
|
||||
word-break: break-word;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (C) 2026 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
list() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/dashboard/board/list'
|
||||
};
|
||||
},
|
||||
add(params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/dashboard/board/create',
|
||||
params
|
||||
};
|
||||
},
|
||||
update(params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/dashboard/board/update',
|
||||
params
|
||||
};
|
||||
},
|
||||
delete(dashboard_id) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/dashboard/board/delete',
|
||||
params: { dashboard_id }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (C) 2026 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
list(dashboard_kurzbz) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/dashboard/preset/list/'
|
||||
+ encodeURIComponent(dashboard_kurzbz)
|
||||
};
|
||||
},
|
||||
getBatch(params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/dashboard/preset/getBatch',
|
||||
params
|
||||
};
|
||||
},
|
||||
addWidget(params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/dashboard/preset/addWidget',
|
||||
params
|
||||
};
|
||||
},
|
||||
removeWidget(params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/dashboard/preset/removeWidget',
|
||||
params
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (C) 2026 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
get(dashboard) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/dashboard/user/get/' + dashboard
|
||||
};
|
||||
},
|
||||
addWidget(dashboard, widget) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/dashboard/user/addWidget',
|
||||
params: {
|
||||
dashboard,
|
||||
widget
|
||||
}
|
||||
};
|
||||
},
|
||||
removeWidget(dashboard, widget) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/dashboard/user/removeWidget',
|
||||
params: {
|
||||
dashboard,
|
||||
widget
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Copyright (C) 2026 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
get(widget) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/dashboard/widget/get/' + widget
|
||||
};
|
||||
},
|
||||
list(dashboard) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/dashboard/widget/list/' + dashboard
|
||||
};
|
||||
},
|
||||
listAllowed(dashboard) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/dashboard/widget/listAllowed/' + dashboard
|
||||
};
|
||||
},
|
||||
setAllowed(dashboard_id, widget_id, allowed) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/dashboard/widget/setAllowed',
|
||||
params: {
|
||||
dashboard_id, widget_id, allowed
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* 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 {
|
||||
getFerien(filterVonDatum, filterBisDatum) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/education/ferien/getFerien',
|
||||
params: {
|
||||
filterVonDatum,
|
||||
filterBisDatum
|
||||
}
|
||||
};
|
||||
},
|
||||
getOe() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/education/ferien/getOe'
|
||||
};
|
||||
},
|
||||
getStudienplaene(oe_kurzbz, vondatum, bisdatum) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/education/ferien/getStudienplaene',
|
||||
params: {
|
||||
oe_kurzbz,
|
||||
vondatum,
|
||||
bisdatum
|
||||
}
|
||||
};
|
||||
},
|
||||
getFerientypen() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/education/ferien/getFerientypen'
|
||||
};
|
||||
},
|
||||
getDefaultVonBis() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/education/ferien/getDefaultVonBis'
|
||||
};
|
||||
},
|
||||
insert(params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/education/ferien/insert',
|
||||
params
|
||||
};
|
||||
},
|
||||
update(params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/education/ferien/update',
|
||||
params
|
||||
};
|
||||
},
|
||||
delete(ferien_id) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/education/ferien/delete',
|
||||
params: { ferien_id }
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -17,13 +17,16 @@
|
||||
|
||||
export default {
|
||||
getMessages(params) {
|
||||
let url = 'api/frontend/v1/messages/messages/getMessages'
|
||||
+ '/' + params.id
|
||||
+ '/' + params.type;
|
||||
if(params.size && params.page) {
|
||||
url += '/' + params.size
|
||||
+ '/' + params.page;
|
||||
}
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/messages/messages/getMessages/'
|
||||
+ params.id + '/'
|
||||
+ params.type + '/'
|
||||
+ params.size + '/'
|
||||
+ params.page
|
||||
url: url
|
||||
};
|
||||
},
|
||||
getVorlagen(){
|
||||
|
||||
@@ -38,6 +38,10 @@ export default {
|
||||
};
|
||||
},
|
||||
insert(params) {
|
||||
if(params.betrag)
|
||||
{
|
||||
params.betrag = params.betrag.replace(',', '.');
|
||||
}
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/stv/konto/insert',
|
||||
@@ -52,6 +56,10 @@ export default {
|
||||
};
|
||||
},
|
||||
edit(params) {
|
||||
if(params.betrag)
|
||||
{
|
||||
params.betrag = params.betrag.replace(',', '.');
|
||||
}
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/stv/konto/update',
|
||||
@@ -65,10 +73,14 @@ export default {
|
||||
params: { buchungsnr }
|
||||
};
|
||||
},
|
||||
getBuchungstypen() {
|
||||
getBuchungstypen(studiensemester_kurzbz) {
|
||||
let url = 'api/frontend/v1/stv/konto/getBuchungstypen'
|
||||
if (!!studiensemester_kurzbz)
|
||||
url = url + '/' + encodeURIComponent(studiensemester_kurzbz);
|
||||
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/stv/konto/getBuchungstypen'
|
||||
url: url
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,16 +1,67 @@
|
||||
import {CoreNavigationCmpt} from '../../components/navigation/Navigation.js';
|
||||
import { CoreNavigationCmpt } from '../../components/navigation/Navigation.js';
|
||||
import DashboardAdmin from '../../components/Dashboard/Admin.js';
|
||||
|
||||
import PluginsPhrasen from '../../plugins/Phrasen.js';
|
||||
|
||||
import ApiRenderers from '../../api/factory/renderers.js';
|
||||
|
||||
const app = Vue.createApp({
|
||||
name: 'AdminApp',
|
||||
data: () => ({
|
||||
appSideMenuEntries: {}
|
||||
}),
|
||||
components: {
|
||||
CoreNavigationCmpt,
|
||||
DashboardAdmin
|
||||
}
|
||||
name: 'DashboardAdminApp',
|
||||
data: () => ({
|
||||
appSideMenuEntries: {},
|
||||
renderers: null
|
||||
}),
|
||||
components: {
|
||||
CoreNavigationCmpt,
|
||||
DashboardAdmin
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
// TODO(chris): move those two into the components that need it
|
||||
renderers: Vue.computed(() => this.renderers),
|
||||
timezone: FHC_JS_DATA_STORAGE_OBJECT.timezone
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$api
|
||||
.call(ApiRenderers.loadRenderers())
|
||||
.then(res => {
|
||||
for (let rendertype of Object.keys(res.data)) {
|
||||
let modalTitle = null;
|
||||
let modalContent = null;
|
||||
let calendarEvent = null;
|
||||
if (res.data[rendertype].modalTitle)
|
||||
modalTitle = Vue.markRaw(Vue.defineAsyncComponent(() => import(res.data[rendertype].modalTitle)));
|
||||
if (res.data[rendertype].modalContent)
|
||||
modalContent = Vue.markRaw(Vue.defineAsyncComponent(() => import(res.data[rendertype].modalContent)));
|
||||
if (res.data[rendertype].calendarEvent)
|
||||
calendarEvent = Vue.markRaw(Vue.defineAsyncComponent(() => import(res.data[rendertype].calendarEvent)));
|
||||
|
||||
if (res.data[rendertype].calendarEventStyles) {
|
||||
var head = document.head;
|
||||
if (!head.querySelector(`link[href="${res.data[rendertype].calendarEventStyles}"]`)) {
|
||||
var link = document.createElement("link");
|
||||
link.type = "text/css";
|
||||
link.rel = "stylesheet";
|
||||
link.href = res.data[rendertype].calendarEventStyles;
|
||||
head.appendChild(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.renderers === null) {
|
||||
this.renderers = {};
|
||||
}
|
||||
if (!this.renderers[rendertype]) {
|
||||
this.renderers[rendertype] = {}
|
||||
}
|
||||
this.renderers[rendertype].modalTitle = modalTitle;
|
||||
this.renderers[rendertype].modalContent = modalContent;
|
||||
this.renderers[rendertype].calendarEvent = calendarEvent;
|
||||
}
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemErrors);
|
||||
}
|
||||
});
|
||||
app.use(PluginsPhrasen);
|
||||
app.directive('tooltip', primevue.tooltip);
|
||||
app.mount('#main');
|
||||
@@ -0,0 +1,17 @@
|
||||
import {CoreNavigationCmpt} from '../../components/navigation/Navigation.js';
|
||||
import CoreDashboard from '../../components/Dashboard/Dashboard.js';
|
||||
import PluginsPhrasen from '../../plugins/Phrasen.js';
|
||||
|
||||
const app = Vue.createApp({
|
||||
name: 'DashboardPreviewApp',
|
||||
data: () => ({
|
||||
appSideMenuEntries: {}
|
||||
}),
|
||||
components: {
|
||||
CoreNavigationCmpt,
|
||||
CoreDashboard
|
||||
}
|
||||
});
|
||||
app.use(PluginsPhrasen);
|
||||
app.directive('tooltip', primevue.tooltip);
|
||||
app.mount('#main');
|
||||
@@ -0,0 +1,12 @@
|
||||
import Ferienverwaltung from '../../../components/Ferienverwaltung/Ferienverwaltung.js';
|
||||
import PluginsPhrasen from '../../../plugins/Phrasen.js';
|
||||
|
||||
const app = Vue.createApp({
|
||||
name: 'FerienverwaltungApp',
|
||||
components: {
|
||||
Ferienverwaltung
|
||||
}
|
||||
});
|
||||
app
|
||||
.use(PluginsPhrasen)
|
||||
.mount('#main');
|
||||
@@ -17,7 +17,7 @@ export default {
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button type="button" class="btn btn-primary" @click="result=true;this.hide()">OK</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{this.$p.t('ui', 'cancel')}}</button>
|
||||
</template>
|
||||
</bs-modal>`
|
||||
}
|
||||
|
||||
@@ -180,7 +180,7 @@ export const AbgabetoolAssistenz = {
|
||||
// frozen: true,
|
||||
// width: 40
|
||||
// },
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4details'))), field: 'details', headerFilter: false, headerSort: false, formatter: this.formAction, tooltip:false, minWidth: 150, cssClass: 'sticky-col'},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4details'))), field: 'details', headerFilter: false, headerSort: false, formatter: this.formAction, tooltip:false, minWidth: 100, cssClass: 'sticky-col'},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4personenkennzeichen'))), headerFilter: true, field: 'pkz', formatter: this.pkzTextFormatter, widthGrow: 1, tooltip: false},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4vorname'))), field: 'student_vorname', headerFilter: true, formatter: this.centeredTextFormatter,widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('abgabetool/c4nachname'))), field: 'student_nachname', headerFilter: true, formatter: this.centeredTextFormatter, widthGrow: 1},
|
||||
@@ -226,7 +226,7 @@ export const AbgabetoolAssistenz = {
|
||||
field: 'qgate2Status', formatter: this.centeredTextFormatter, widthGrow: 1, width: 220, tooltip: false},
|
||||
],
|
||||
persistence: false,
|
||||
persistenceID: "abgabetool_2026_02_26"
|
||||
persistenceID: "abgabetool_2026_03_16"
|
||||
},
|
||||
abgabeTableEventHandlers: [
|
||||
{
|
||||
@@ -645,7 +645,7 @@ export const AbgabetoolAssistenz = {
|
||||
actionButtons.className = "d-flex gap-3"; // you can keep Bootstrap gap if loaded
|
||||
actionButtons.style.display = "flex";
|
||||
actionButtons.style.alignItems = "stretch"; // buttons stretch to full height
|
||||
actionButtons.style.justifyContent = "center";
|
||||
actionButtons.style.justifyContent = "start";
|
||||
actionButtons.style.height = "100%"; // full grid cell height
|
||||
|
||||
const val = cell.getValue();
|
||||
@@ -675,8 +675,20 @@ export const AbgabetoolAssistenz = {
|
||||
createButton('fa fa-timeline', 'abgabetool/c4termineTimeLine', () => this.openTimeline(val))
|
||||
);
|
||||
|
||||
if(val.latestTerminWithUpload) {
|
||||
actionButtons.append(
|
||||
createButton('fa fa-download', 'abgabetool/c4downloadLatestAbgabe', () => this.downloadAbgabe(val.latestTerminWithUpload.paabgabe_id, val.student_uid, val.projektarbeit_id))
|
||||
)
|
||||
}
|
||||
|
||||
return actionButtons;
|
||||
},
|
||||
downloadAbgabe(paabgabe_id, student_uid, projektarbeit_id) {
|
||||
const url = `/api/frontend/v1/Abgabe/getStudentProjektarbeitAbgabeFile?paabgabe_id=${paabgabe_id}&student_uid=${student_uid}&projektarbeit_id=${projektarbeit_id}`;
|
||||
|
||||
window.open(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + url)
|
||||
// this.$api.call(ApiAbgabe.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid))
|
||||
},
|
||||
|
||||
undoSelection(cell) {
|
||||
// checks if cells row is selected and unselects -> imitates columns which dont trigger row selection
|
||||
@@ -780,6 +792,8 @@ export const AbgabetoolAssistenz = {
|
||||
// TODO: mehrsprachig englisch
|
||||
projekt.note_bez = opt.bezeichnung
|
||||
}
|
||||
|
||||
const latestTerminWithUpload = this.findLatestTerminWithUpload(projekt)
|
||||
|
||||
return {
|
||||
...projekt,
|
||||
@@ -787,6 +801,7 @@ export const AbgabetoolAssistenz = {
|
||||
details: {
|
||||
student_uid: projekt.student_uid,
|
||||
projektarbeit_id: projekt.projektarbeit_id,
|
||||
latestTerminWithUpload: latestTerminWithUpload ?? null
|
||||
},
|
||||
pkz: this.buildPKZ(projekt),
|
||||
beurteilung: projekt.beurteilungLink ?? null,
|
||||
@@ -800,6 +815,15 @@ export const AbgabetoolAssistenz = {
|
||||
}
|
||||
})
|
||||
},
|
||||
findLatestTerminWithUpload(projekt) {
|
||||
const withAbgabedatumSorted = projekt?.abgabetermine?.filter(t => t.abgabedatum != null)?.sort((a,b) => a < b)
|
||||
|
||||
if(withAbgabedatumSorted.length) {
|
||||
return withAbgabedatumSorted[0]
|
||||
}
|
||||
|
||||
return null
|
||||
},
|
||||
createInfoString(data) {
|
||||
let str = '';
|
||||
|
||||
@@ -1413,9 +1437,12 @@ export const AbgabetoolAssistenz = {
|
||||
|
||||
<div id="abgabetable" style="max-height:40vw;">
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<div class="col-auto me-auto">
|
||||
<h2 tabindex="1">{{$p.t('abgabetool/abgabetoolTitle')}}</h2>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<label class="col-form-label">{{$capitalize($p.t('lehre/studiengang'))}}:</label>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<Dropdown
|
||||
:placeholder="$capitalize($p.t('lehre/studiengang'))"
|
||||
@@ -1430,6 +1457,9 @@ export const AbgabetoolAssistenz = {
|
||||
</template>
|
||||
</Dropdown>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<label class="col-form-label">{{$capitalize($p.t('lehre/note'))}}:</label>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<Dropdown
|
||||
:placeholder="$p.t('lehre/note')"
|
||||
|
||||
@@ -667,8 +667,10 @@ export const AbgabetoolMitarbeiter = {
|
||||
setDetailComponent(details){
|
||||
this.loading=true
|
||||
|
||||
const pa = this.projektarbeiten?.retval?.find(projekarbeit => projekarbeit.projektarbeit_id == details.projektarbeit_id)
|
||||
const projektarbeiten = this.projektarbeiten?.retval ?? this.projektarbeiten
|
||||
|
||||
const pa = projektarbeiten.find(projekarbeit => projekarbeit.projektarbeit_id == details.projektarbeit_id)
|
||||
|
||||
let paIsBenotet = false
|
||||
if(pa.note !== undefined && pa.note !== null) {
|
||||
// check if the note is not defined as a non final projektarbeit note
|
||||
|
||||
@@ -3,15 +3,20 @@ import DashboardAdminEdit from "./Admin/Edit.js";
|
||||
import DashboardAdminWidgets from "./Admin/Widgets.js";
|
||||
import DashboardAdminPresets from "./Admin/Presets.js";
|
||||
|
||||
import ApiDashboardBoard from "../../api/factory/dashboard/board.js";
|
||||
import ApiDashboardWidget from "../../api/factory/dashboard/widget.js";
|
||||
|
||||
export default {
|
||||
name: 'DashboardAdmin',
|
||||
components: {
|
||||
DashboardAdminEdit,
|
||||
DashboardAdminWidgets,
|
||||
DashboardAdminPresets
|
||||
DashboardAdminPresets,
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
adminMode: true
|
||||
adminMode: true,
|
||||
widgetsSetup: Vue.computed(() => this.dashboards[this.current] ? this.dashboards[this.current].widgetSetup : null)
|
||||
};
|
||||
},
|
||||
data() {
|
||||
@@ -22,9 +27,6 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
apiurl() {
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/dashboard';
|
||||
},
|
||||
dashboard() {
|
||||
return this.dashboards.find(el => el.dashboard_id == this.current);
|
||||
}
|
||||
@@ -35,33 +37,50 @@ export default {
|
||||
BsPrompt.popup('New Dashboard name').then(
|
||||
name => {
|
||||
_name = name;
|
||||
return axios.post(this.apiurl + '/Dashboard/create', {
|
||||
const params = {
|
||||
dashboard_kurzbz: name
|
||||
})
|
||||
}
|
||||
).then(res => {
|
||||
let newDashboard = {
|
||||
dashboard_id: res.data.retval,
|
||||
dashboard_kurzbz: _name,
|
||||
beschreibung: ''
|
||||
};
|
||||
this.dashboards.push(newDashboard);
|
||||
this.current = newDashboard.dashboard_id;
|
||||
}).catch(err => err !== undefined ? console.error('ERROR:', err) : 0);
|
||||
};
|
||||
return this.$api
|
||||
.call(ApiDashboardBoard.add(params))
|
||||
.then(response =>{
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
|
||||
|
||||
let newDashboard = {
|
||||
dashboard_id: response.data,
|
||||
dashboard_kurzbz: _name,
|
||||
beschreibung: ''
|
||||
};
|
||||
this.dashboards.push(newDashboard);
|
||||
this.current = newDashboard.dashboard_id;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
});
|
||||
},
|
||||
dashboardUpdate(dashboard) {
|
||||
// TODO(chris): Loading or message
|
||||
axios.post(this.apiurl + '/Dashboard/update', dashboard).then(() => {
|
||||
let old = this.dashboards.find(el => el.dashboard_id == dashboard.dashboard_id);
|
||||
old.dashboard_kurzbz = dashboard.dashboard_kurzbz;
|
||||
old.beschreibung = dashboard.beschreibung;
|
||||
}).catch(err => console.error('ERROR:', err));
|
||||
return this.$api
|
||||
.call(ApiDashboardBoard.update(dashboard))
|
||||
.then(response =>{
|
||||
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
|
||||
|
||||
let old = this.dashboards.find(el => el.dashboard_id == dashboard.dashboard_id);
|
||||
old.dashboard_kurzbz = dashboard.dashboard_kurzbz;
|
||||
old.beschreibung = dashboard.beschreibung;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
dashboardDelete(dashboard_id) {
|
||||
axios.post(this.apiurl + '/Dashboard/delete', {dashboard_id}).then(() => {
|
||||
this.current = -1;
|
||||
this.dashboards = this.dashboards.filter(el => el.dashboard_id != dashboard_id);
|
||||
}).catch(err => console.error('ERROR:', err));
|
||||
return this.$api
|
||||
.call(ApiDashboardBoard.delete(dashboard_id))
|
||||
.then(response => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
|
||||
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError)
|
||||
.finally(() => {
|
||||
this.current = -1;
|
||||
this.dashboards = this.dashboards.filter(el => el.dashboard_id != dashboard_id);
|
||||
});
|
||||
},
|
||||
assignWidgets(widgets) {
|
||||
this.widgets = widgets;
|
||||
@@ -72,22 +91,35 @@ export default {
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get(this.apiurl + '/Dashboard').then(res => {
|
||||
this.dashboards = res.data.retval;
|
||||
}).catch(err => console.error('ERROR:', err));
|
||||
this.$api
|
||||
.call(ApiDashboardBoard.list())
|
||||
.then(result => {
|
||||
this.dashboards = result.data.retval;
|
||||
for (const dashboard of this.dashboards) {
|
||||
this.$api
|
||||
.call(ApiDashboardWidget.list(dashboard.dashboard_id))
|
||||
.then(res => {
|
||||
dashboard.widgetSetup = res.data;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
}
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
template: `<div class="dashboard-admin">
|
||||
|
||||
<div class="input-group">
|
||||
<label for="dashbaord-select" class="input-group-text">Dashboard:</label>
|
||||
<select id="dashbaord-select" class="form-select" v-model="current">
|
||||
<label for="dashboard-select" class="input-group-text">Dashboard:</label>
|
||||
<select id="dashboard-select" class="form-select" v-model="current">
|
||||
<option v-for="dashboard in dashboards" :key="dashboard.dashboard_id" :value="dashboard.dashboard_id">{{dashboard.dashboard_kurzbz}}</option>
|
||||
</select>
|
||||
<button class="btn btn-outline-secondary" type="button" @click="dashboardAdd"><i class="fa-solid fa-plus"></i></button>
|
||||
</div>
|
||||
|
||||
<div v-if="dashboard">
|
||||
<ul class="nav nav-tabs mt-3" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="edit-tab" data-bs-toggle="tab" data-bs-target="#edit" type="button" role="tab" aria-controls="edit" aria-selected="false">Edit</button>
|
||||
<button class="nav-link" id="edit-tab" data-bs-toggle="tab" data-bs-target="#edit" type="button" role="tab" aria-controls="edit" aria-selected="false">{{this.$p.t('ui', 'bearbeiten')}}</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="widgets-tab" data-bs-toggle="tab" data-bs-target="#widgets" type="button" role="tab" aria-controls="widgets" aria-selected="true">Widgets</button>
|
||||
@@ -101,7 +133,7 @@ export default {
|
||||
<dashboard-admin-edit v-bind="dashboard" :key="dashboard.dashboard_id" @change="dashboardUpdate($event)" @delete="dashboardDelete($event)"></dashboard-admin-edit>
|
||||
</div>
|
||||
<div class="tab-pane fade show active" id="widgets" role="tabpanel" aria-labelledby="widgets-tab">
|
||||
<dashboard-admin-widgets :key="dashboard.dashboard_id" :dashboard_id="dashboard.dashboard_id" :widgets="widgets" @change="test" @assign-widgets="assignWidgets"></dashboard-admin-widgets>
|
||||
<dashboard-admin-widgets :key="dashboard.dashboard_id" :dashboard_id="dashboard.dashboard_id" :widgets="widgets" @assign-widgets="assignWidgets"></dashboard-admin-widgets>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="presets" role="tabpanel" aria-labelledby="presets-tab">
|
||||
<dashboard-admin-presets :dashboard="dashboard.dashboard_kurzbz" :widgets="widgets"></dashboard-admin-presets>
|
||||
|
||||
@@ -18,7 +18,8 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
sendDelete() {
|
||||
BsConfirm.popup('Sure?').then(() => this.$emit('delete', this.dashboard_id)).catch();
|
||||
BsConfirm.popup(this.$p.t('ui', 'confirm_delete') + " " + this.$p.t('ui', 'deleteInfo'))
|
||||
.then(() => this.$emit('delete', this.dashboard_id)).catch();
|
||||
}
|
||||
},
|
||||
template: `<div class="dashboard-admin-edit px-3">
|
||||
@@ -31,8 +32,8 @@ export default {
|
||||
<textarea id="dashboard-admin-edit-beschreibung" class="form-control" v-model="desc"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<button class="btn btn-danger" @click="sendDelete">Delete</button>
|
||||
<button class="btn btn-primary" @click="$emit('change', {dashboard_id,dashboard_kurzbz:kurzbz,beschreibung:desc})">Update</button>
|
||||
<button class="btn btn-danger" @click="sendDelete">{{this.$p.t('ui', 'loeschen')}}</button>
|
||||
<button class="btn btn-primary" @click="$emit('change', {dashboard_id,dashboard_kurzbz:kurzbz,beschreibung:desc})">{{this.$p.t('ui', 'btnAktualisieren')}}</button>
|
||||
</div>
|
||||
</div>`
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import DashboardSection from "../Section.js";
|
||||
import DashboardWidgetPicker from "../Widget/Picker.js";
|
||||
import ObjectUtils from "../../../helpers/ObjectUtils.js";
|
||||
import ApiDashboardPreset from "../../../api/factory/dashboard/preset.js";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@@ -17,9 +18,6 @@ export default {
|
||||
tmpLoading: ''
|
||||
}),
|
||||
computed: {
|
||||
apiurl() {
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/dashboard';
|
||||
},
|
||||
pickerWidgets() {
|
||||
return this.widgets.filter(widget => widget.allowed);
|
||||
}
|
||||
@@ -28,6 +26,7 @@ export default {
|
||||
widgetAdd(section_name, widget) {
|
||||
this.$refs.widgetpicker.getWidget().then(widget_id => {
|
||||
widget.widget = widget_id;
|
||||
widget.id = 'loading_' + String((new Date()).valueOf());
|
||||
delete widget.custom;
|
||||
widget.preset = 1;
|
||||
let loading = {...widget};
|
||||
@@ -36,130 +35,153 @@ export default {
|
||||
if (section.name == section_name)
|
||||
section.widgets.push(loading);
|
||||
});
|
||||
|
||||
axios.post(this.apiurl + '/Config/addWidgetsToPreset', {
|
||||
db: this.dashboard,
|
||||
|
||||
const params = {
|
||||
dashboard: this.dashboard,
|
||||
funktion_kurzbz: section_name,
|
||||
widgets: [widget]
|
||||
}).then(result => {
|
||||
let newId = Object.keys(result.data.retval.data[section_name].widgets).pop();
|
||||
widget.id = newId;
|
||||
widget.custom = 1;
|
||||
this.sections.forEach(section => {
|
||||
if (section.name == section_name) {
|
||||
section.widgets.splice(section.widgets.indexOf(loading),1);
|
||||
section.widgets.push(widget);
|
||||
}
|
||||
});
|
||||
}).catch(error => {
|
||||
console.error('ERROR: ', error);
|
||||
alert('ERROR: ' + error.response.data.retval);
|
||||
});
|
||||
}).catch(() => {});
|
||||
widget
|
||||
};
|
||||
|
||||
return this.$api
|
||||
.call(ApiDashboardPreset.addWidget(params))
|
||||
.then(result => {
|
||||
let newId = result.data;
|
||||
widget.id = newId;
|
||||
widget.custom = 1;
|
||||
this.sections.forEach(section => {
|
||||
if (section.name == section_name) {
|
||||
section.widgets.splice(section.widgets.indexOf(loading),1);
|
||||
section.widgets.push(widget);
|
||||
}
|
||||
});
|
||||
this.funktionen.forEach(funktion => {
|
||||
if(funktion.funktion_kurzbz === section_name && funktion.has_preset < 1) {
|
||||
funktion.has_preset = 1;
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
widgetUpdate(section_name, payload) {
|
||||
payload = payload[section_name];
|
||||
for (var k in payload) {
|
||||
for (var i in this.sections) {
|
||||
if (this.sections[i].name == section_name) {
|
||||
for (var wid in this.sections[i].widgets) {
|
||||
if (this.sections[i].widgets[wid].id == k) {
|
||||
payload[k] = ObjectUtils.mergeDeep(this.sections[i].widgets[wid], payload[k]);
|
||||
// NOTE(chris): remove internal props
|
||||
for (var prop in {_x:1,_y:1,_w:1,_h:1,index:1,id:1})
|
||||
if (payload[k][prop])
|
||||
delete payload[k][prop];
|
||||
break;
|
||||
}
|
||||
}
|
||||
const section = this.sections.find(section => section.name == section_name);
|
||||
for (var wid in section.widgets) {
|
||||
if (section.widgets[wid].id == k) {
|
||||
payload[k] = ObjectUtils.mergeDeep(section.widgets[wid], payload[k]);
|
||||
// NOTE(chris): remove internal props
|
||||
for (var prop of ['_x', '_y', '_w', '_h', 'index', 'id'])
|
||||
if (payload[k][prop])
|
||||
delete payload[k][prop];
|
||||
break;
|
||||
}
|
||||
}
|
||||
payload[k].widgetid = k;
|
||||
delete payload[k].custom;
|
||||
}
|
||||
axios.post(this.apiurl + '/Config/addWidgetsToPreset', {
|
||||
db: this.dashboard,
|
||||
funktion_kurzbz: section_name,
|
||||
widgets: payload
|
||||
}).then(() => {
|
||||
this.sections.forEach(section => {
|
||||
if (section.name == section_name) {
|
||||
section.widgets.forEach((widget, i) => {
|
||||
if (payload[widget.id]) {
|
||||
payload[widget.id].id = widget.id;
|
||||
payload[widget.id].index = widget.index;
|
||||
section.widgets[i] = payload[widget.id];
|
||||
section.widgets[i].custom = 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}).catch(error => {
|
||||
// TODO(chris): revert placement on failure
|
||||
console.error('ERROR: ', error);
|
||||
alert('ERROR: ' + error.response.data.retval);
|
||||
});
|
||||
this.$api
|
||||
.call(Object.entries(payload).map(([key, widget]) => [
|
||||
key,
|
||||
ApiDashboardPreset.addWidget({
|
||||
dashboard: this.dashboard,
|
||||
funktion_kurzbz: section_name,
|
||||
widget
|
||||
})
|
||||
]))
|
||||
.then(result => {
|
||||
this.sections.forEach(section => {
|
||||
if (section.name == section_name) {
|
||||
section.widgets.forEach((widget, i) => {
|
||||
if (payload[widget.id]) {
|
||||
payload[widget.id].id = widget.id;
|
||||
payload[widget.id].index = widget.index;
|
||||
section.widgets[i] = payload[widget.id];
|
||||
section.widgets[i].custom = 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
widgetRemove(section_name, id) {
|
||||
axios.post(this.apiurl + '/Config/removeWidgetFromPreset', {
|
||||
const params = {
|
||||
db: this.dashboard,
|
||||
funktion_kurzbz: section_name,
|
||||
widgetid: id
|
||||
}).then(() => {
|
||||
this.sections.forEach(section => {
|
||||
if (section.name == section_name)
|
||||
section.widgets = section.widgets.filter(widget => widget.id != id);
|
||||
});
|
||||
}).catch(error => {
|
||||
console.error('ERROR: ', error);
|
||||
alert('ERROR: ' + error.response.data.retval);
|
||||
});
|
||||
};
|
||||
return this.$api
|
||||
.call(ApiDashboardPreset.removeWidget(params))
|
||||
.then(result => {
|
||||
this.sections.forEach(section => {
|
||||
if (section.name == section_name)
|
||||
section.widgets = section.widgets.filter(widget => widget.id != id);
|
||||
});
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
loadSections(evt) {
|
||||
let funktionen = Array.from(evt.target.querySelectorAll("option:checked"),e=>e.value);
|
||||
this.sections = [];
|
||||
this.tmpLoading = funktionen.join('###');
|
||||
axios.get(this.apiurl + '/Config/presetBatch', {params: {
|
||||
|
||||
const params = {
|
||||
db: this.dashboard,
|
||||
funktionen
|
||||
}}).then(res => {
|
||||
if (this.tmpLoading !== funktionen.join('###'))
|
||||
return; // NOTE(chris): prevent race condition
|
||||
for (var section in res.data.retval) {
|
||||
let widgets = [];
|
||||
for (var wid in res.data.retval[section]) {
|
||||
res.data.retval[section][wid].id = wid;
|
||||
res.data.retval[section][wid].custom = 1;
|
||||
widgets.push(res.data.retval[section][wid]);
|
||||
};
|
||||
|
||||
return this.$api
|
||||
.call(ApiDashboardPreset.getBatch(params))
|
||||
.then(result => {
|
||||
if (this.tmpLoading !== funktionen.join('###'))
|
||||
return; // NOTE(chris): prevent race condition
|
||||
for (var section in result.data) {
|
||||
let widgets = [];
|
||||
for (var wid in result.data[section]) {
|
||||
result.data[section][wid].id = wid;
|
||||
result.data[section][wid].custom = 1;
|
||||
widgets.push(result.data[section][wid]);
|
||||
}
|
||||
this.sections.push({
|
||||
name: section,
|
||||
widgets
|
||||
});
|
||||
}
|
||||
this.sections.push({
|
||||
name: section,
|
||||
widgets
|
||||
});
|
||||
}
|
||||
}).catch(err => console.error('ERROR:', err));
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
},
|
||||
loadFunktionen() {
|
||||
this.$api
|
||||
.call(ApiDashboardPreset.list(this.dashboard))
|
||||
.then(result => {
|
||||
this.funktionen = result.data;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get(this.apiurl + '/Config/funktionen').then(res => {
|
||||
this.funktionen = {general: 'GENERAL'};
|
||||
res.data.retval.forEach(funktion => {
|
||||
this.funktionen[funktion.funktion_kurzbz] = funktion.beschreibung;
|
||||
});
|
||||
}).catch(err => console.error('ERROR:', err));
|
||||
this.loadFunktionen();
|
||||
},
|
||||
watch: {
|
||||
dashboard() {
|
||||
// TODO(chris): this should be done without a watcher
|
||||
this.loadSections({target:this.$refs.funktionenList});
|
||||
this.loadFunktionen();
|
||||
}
|
||||
},
|
||||
template: `<div class="dashboard-admin-presets">
|
||||
<div class="row">
|
||||
<div class="col-3">
|
||||
<select ref="funktionenList" style="height:30em" class="form-control" multiple @input="loadSections">
|
||||
<option v-for="name,id in funktionen" :key="id" :value="id">{{ name }}</option>
|
||||
<option
|
||||
v-for="funktion in funktionen"
|
||||
:key="funktion.funktion_kurzbz"
|
||||
:value="funktion.funktion_kurzbz"
|
||||
:class="(funktion.has_preset > 0) ? 'fw-bold' : ''"
|
||||
>{{ funktion.beschreibung }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-9">
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import ApiDashboardWidget from "../../../api/factory/dashboard/widget.js";
|
||||
|
||||
export default {
|
||||
emits: [
|
||||
"change",
|
||||
@@ -7,34 +9,25 @@ export default {
|
||||
dashboard_id: Number,
|
||||
widgets: Array
|
||||
},
|
||||
computed: {
|
||||
apiurl() {
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/dashboard';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sendChange(widget_id) {
|
||||
let allow = !this.widgets.find(el => el.widget_id == widget_id).allowed;
|
||||
axios.post(this.apiurl + '/Widget/setAllowed', {
|
||||
dashboard_id: this.dashboard_id,
|
||||
widget_id,
|
||||
action: allow ? 'add' : 'delete'
|
||||
}).catch(err => console.error('ERROR: ' + err));
|
||||
|
||||
this.$api
|
||||
.call(ApiDashboardWidget.setAllowed(this.dashboard_id, widget_id, allow))
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
axios.get(this.apiurl + '/Widget/getAll', {
|
||||
params:{
|
||||
dashboard_id: this.dashboard_id
|
||||
}
|
||||
}).then(
|
||||
result => {
|
||||
this.$emit('assignWidgets', result.data.retval.map(el => ({
|
||||
this.$api
|
||||
.call(ApiDashboardWidget.list(this.dashboard_id))
|
||||
.then(result => {
|
||||
this.$emit('assignWidgets', result.data.map(el => ({
|
||||
...el,
|
||||
...{setup:JSON.parse(el.setup),arguments:JSON.parse(el.arguments),allowed:!!el.allowed}
|
||||
allowed: !!el.allowed
|
||||
})));
|
||||
}
|
||||
).catch(err => console.error('ERROR:', err));
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
template: `
|
||||
<div class="dashboard-admin-widgets">
|
||||
|
||||
@@ -2,7 +2,8 @@ import DashboardSection from "./Section.js";
|
||||
import DashboardWidgetPicker from "./Widget/Picker.js";
|
||||
import ObjectUtils from "../../helpers/ObjectUtils.js";
|
||||
|
||||
import ApiDashboard from '../../api/factory/cis/dashboard.js';
|
||||
import ApiDashboardWidget from '../../api/factory/dashboard/widget.js';
|
||||
import ApiDashboardUser from '../../api/factory/dashboard/user.js';
|
||||
|
||||
export default {
|
||||
name: 'Dashboard',
|
||||
@@ -20,181 +21,147 @@ export default {
|
||||
type: Object,
|
||||
required: true,
|
||||
validator(value) {
|
||||
return value && value.name && value.uid && value.timezone
|
||||
return value && value.name && value.timezone
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
sections: [],
|
||||
widgets: null,
|
||||
editMode: false,
|
||||
viewDataInternal: this.viewData
|
||||
widgets: [],
|
||||
originalWidgets: {},
|
||||
widgetsSetup: null,
|
||||
editMode: false
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
editMode: Vue.computed(()=>this.editMode),
|
||||
widgetsSetup: Vue.computed(() => this.widgets),
|
||||
widgetsSetup: Vue.computed(() => this.widgetsSetup),
|
||||
timezone: Vue.computed(() => this.viewData.timezone)
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
apiurl() {
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/dashboard';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
widgetAdd(section_name, widget) {
|
||||
if (this.widgets === null) {
|
||||
axios.get(this.apiurl + '/Widget/getWidgetsForDashboard', {params:{
|
||||
db: this.dashboard
|
||||
}}).then(res => {
|
||||
res.data.retval.forEach(widget => {
|
||||
widget.arguments = JSON.parse(widget.arguments);
|
||||
widget.setup = JSON.parse(widget.setup);
|
||||
});
|
||||
this.widgets = res.data.retval;
|
||||
}).catch(err => console.error('ERROR:', err));
|
||||
}
|
||||
this.$refs.widgetpicker.getWidget().then(widget_id => {
|
||||
widget.widget = widget_id;
|
||||
widget.id = 'loading_' + String((new Date()).valueOf());
|
||||
let loading = {...widget};
|
||||
loading.loading = true;
|
||||
this.sections.forEach(section => {
|
||||
if (section.name == section_name)
|
||||
section.widgets.push(loading);
|
||||
});
|
||||
|
||||
axios.post(this.apiurl + '/Config/addWidgetsToUserOverride', {
|
||||
db: this.dashboard,
|
||||
funktion_kurzbz: section_name,
|
||||
widgets: [widget]
|
||||
}).then(result => {
|
||||
let newId = Object.keys(result.data.retval.data[section_name].widgets).pop();
|
||||
widget.id = newId;
|
||||
this.sections.forEach(section => {
|
||||
if (section.name == section_name) {
|
||||
section.widgets.splice(section.widgets.indexOf(loading),1);
|
||||
section.widgets.push(widget);
|
||||
}
|
||||
});
|
||||
}).catch(error => {
|
||||
console.error('ERROR: ', error);
|
||||
alert('ERROR: ' + error.response.data.retval);
|
||||
});
|
||||
}).catch(() => {});
|
||||
// TODO(chris): remove section_name? (change order of params => get rid of it)
|
||||
this.$refs.widgetpicker
|
||||
.getWidget()
|
||||
.then(widget_id => {
|
||||
widget.widget = widget_id;
|
||||
widget.id = 'loading_' + String((new Date()).valueOf());
|
||||
let loading = { ...widget };
|
||||
loading.loading = true;
|
||||
this.widgets.push(loading);
|
||||
|
||||
this.$api
|
||||
.call(ApiDashboardUser.addWidget(this.dashboard, widget))
|
||||
.then(result => {
|
||||
widget.id = result.data;
|
||||
this.widgets.splice(this.widgets.indexOf(loading), 1);
|
||||
this.widgets.push(widget);
|
||||
this.originalWidgets[widget.id] = structuredClone(ObjectUtils.deepToRaw(widget));
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
widgetUpdate(section_name, payload) {
|
||||
payload = payload[section_name];
|
||||
for (var k in payload) {
|
||||
for (var i in this.sections) {
|
||||
if (this.sections[i].name == section_name) {
|
||||
for (var wid in this.sections[i].widgets) {
|
||||
if (this.sections[i].widgets[wid].id == k) {
|
||||
payload[k] = ObjectUtils.mergeDeep(this.sections[i].widgets[wid], payload[k]);
|
||||
// NOTE(chris): remove internal props
|
||||
for (var prop in {_x:1,_y:1,_w:1,_h:1,index:1,id:1,preset:1})
|
||||
if (payload[k][prop])
|
||||
delete payload[k][prop];
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (var wid in this.widgets) {
|
||||
if (this.widgets[wid].id == k) {
|
||||
payload[k] = ObjectUtils.mergeDeep(this.widgets[wid], payload[k]);
|
||||
// NOTE(chris): remove internal props
|
||||
for (var prop of ['_x','_y','_w','_h','index','id','preset'])
|
||||
if (payload[k][prop])
|
||||
delete payload[k][prop];
|
||||
break;
|
||||
}
|
||||
}
|
||||
payload[k].widgetid = k;
|
||||
}
|
||||
axios.post(this.apiurl + '/Config/addWidgetsToUserOverride', {
|
||||
db: this.dashboard,
|
||||
funktion_kurzbz: section_name,
|
||||
widgets: payload
|
||||
}).then(() => {
|
||||
this.sections.forEach(section => {
|
||||
if (section.name == section_name) {
|
||||
section.widgets.forEach((widget, i) => {
|
||||
if (payload[widget.id]) {
|
||||
payload[widget.id].id = widget.id;
|
||||
payload[widget.id].index = widget.index;
|
||||
section.widgets[i] = payload[widget.id];
|
||||
this.$api
|
||||
.call(Object.entries(payload).map(([key, widget]) => [
|
||||
key,
|
||||
ApiDashboardUser.addWidget(this.dashboard, widget)
|
||||
]))
|
||||
.then(result => {
|
||||
const failed = result
|
||||
.filter(o => o.status == 'rejected')
|
||||
.map(o => o.reason.config.errorHeader);
|
||||
|
||||
this.widgets.forEach((widget, i) => {
|
||||
if (failed.includes(widget.id)) {
|
||||
this.widgets[i] = structuredClone(ObjectUtils.deepToRaw(this.originalWidgets[widget.id]));
|
||||
/** NOTE(chris): if you wanna hide or unhide a
|
||||
* preset and it fails: switch around the hidden
|
||||
* value to revert it properly (checkboxes can't
|
||||
* really handle it otherwise)
|
||||
*/
|
||||
if (payload[widget.id].hidden !== undefined) {
|
||||
this.widgets[i].hidden = payload[widget.id].hidden;
|
||||
this.$nextTick(() => {
|
||||
this.widgets[i] = structuredClone(ObjectUtils.deepToRaw(this.originalWidgets[widget.id]));
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}).catch(error => {
|
||||
// TODO(chris): revert placement on failure
|
||||
console.error('ERROR: ', error);
|
||||
alert('ERROR: ' + error.response.data.retval);
|
||||
});
|
||||
} else if (payload[widget.id]) {
|
||||
payload[widget.id].id = widget.id;
|
||||
payload[widget.id].index = widget.index;
|
||||
this.widgets[i] = payload[widget.id];
|
||||
this.originalWidgets[widget.id] = structuredClone(ObjectUtils.deepToRaw(this.widgets[i]));
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
widgetRemove(section_name, id) {
|
||||
axios.post(this.apiurl + '/Config/removeWidgetFromUserOverride', {
|
||||
db: this.dashboard,
|
||||
funktion_kurzbz: section_name,
|
||||
widgetid: id
|
||||
}).then(() => {
|
||||
this.sections.forEach(section => {
|
||||
if (section.name == section_name)
|
||||
section.widgets = section.widgets.filter(widget => widget.id != id);
|
||||
});
|
||||
}).catch(error => {
|
||||
console.error('ERROR: ', error);
|
||||
alert('ERROR: ' + error.response.data.retval);
|
||||
});
|
||||
this.$api
|
||||
.call(ApiDashboardUser.removeWidget(this.dashboard, id))
|
||||
.then(() => {
|
||||
this.widgets = this.widgets.filter(widget => widget.id != id);
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$p.loadCategory('dashboard');
|
||||
axios.get(this.apiurl + '/Widget/getWidgetsForDashboard', {
|
||||
params: {
|
||||
db: this.dashboard
|
||||
}
|
||||
}).then(res => {
|
||||
this.widgets = res.data.retval;
|
||||
}).catch(err => console.error('ERROR:', err));
|
||||
|
||||
axios.get(this.apiurl + '/Config', {params:{
|
||||
db: this.dashboard
|
||||
}}).then(res => {
|
||||
for (var name in res.data.retval) {
|
||||
let widgets = [];
|
||||
let remove = [];
|
||||
for (var wid in res.data.retval[name].widgets) {
|
||||
res.data.retval[name].widgets[wid].id = wid;
|
||||
if (res.data.retval[name].widgets[wid].custom || res.data.retval[name].widgets[wid].preset)
|
||||
widgets.push(res.data.retval[name].widgets[wid]);
|
||||
else
|
||||
this.$api
|
||||
.call(ApiDashboardWidget.listAllowed(this.dashboard))
|
||||
.then(res => {
|
||||
this.widgetsSetup = res.data;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
this.$api
|
||||
.call(ApiDashboardUser.get(this.dashboard))
|
||||
.then(res => {
|
||||
const widgets = [];
|
||||
const remove = [];
|
||||
|
||||
for (var wid in res.data.general.widgets) {
|
||||
let widget = res.data.general.widgets[wid];
|
||||
widget.id = wid;
|
||||
if (widget.custom || widget.preset) {
|
||||
widgets.push(widget);
|
||||
this.originalWidgets[wid] = structuredClone(widget);
|
||||
} else {
|
||||
remove.push(wid);
|
||||
}
|
||||
}
|
||||
this.sections.push({
|
||||
name: name,
|
||||
widgets: widgets
|
||||
});
|
||||
remove.forEach(wid => this.widgetRemove(name, wid));
|
||||
}
|
||||
this.sections = this.sections.sort((section1, section2) => {
|
||||
if(section1.name == 'custom')
|
||||
return 1;
|
||||
if (section2.name == 'custom')
|
||||
return -1;
|
||||
return section2.widgets.length - section1.widgets.length;
|
||||
});
|
||||
}).catch(err => console.error('ERROR:', err));
|
||||
},
|
||||
async beforeMount() {
|
||||
if (!this.viewData.name || !this.viewData.uid) {
|
||||
const res = await this.$api.call(ApiDashboard.getViewData());
|
||||
this.viewDataInternal = res.data
|
||||
}
|
||||
|
||||
remove.forEach(wid => this.widgetRemove('general', wid));
|
||||
|
||||
this.widgets = widgets;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
template: `
|
||||
<div class="core-dashboard">
|
||||
<h3 v-show="viewDataInternal?.name">
|
||||
{{ $p.t('global/personalGreeting', [ viewDataInternal?.name ]) }}
|
||||
<h3>
|
||||
{{ $p.t('global/personalGreeting', [ viewData?.name ]) }}
|
||||
<button style="margin-left: 8px;" class="btn" @click="editMode = !editMode" aria-label="edit dashboard" v-tooltip="{showDelay:1000,value:'edit dashboard'}"><i class="fa-solid fa-gear" aria-hidden="true"></i></button>
|
||||
</h3>
|
||||
<dashboard-section v-for="(section, index) in sections" :key="section.name" :seperator="index" :name="section.name" :widgets="section.widgets" @widgetAdd="widgetAdd" @widgetUpdate="widgetUpdate" @widgetRemove="widgetRemove"></dashboard-section>
|
||||
<dashboard-widget-picker ref="widgetpicker" :widgets="widgets"></dashboard-widget-picker>
|
||||
<dashboard-section :seperator="0" name="general" :widgets="widgets" @widgetAdd="widgetAdd" @widgetUpdate="widgetUpdate" @widgetRemove="widgetRemove"></dashboard-section>
|
||||
<dashboard-widget-picker ref="widgetpicker" :widgets="widgetsSetup"></dashboard-widget-picker>
|
||||
</div>`
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import BsModal from "../Bootstrap/Modal.js";
|
||||
import CachedWidgetLoader from "../../composables/Dashboard/CachedWidgetLoader.js";
|
||||
import { useCachedWidgetLoader } from "../../composables/Dashboard/CachedWidgetLoader.js";
|
||||
import HeightTransition from "../Tranistion/HeightTransition.js";
|
||||
|
||||
export default {
|
||||
@@ -70,6 +70,14 @@ export default {
|
||||
ready() {
|
||||
return this.component && this.arguments !== null;
|
||||
},
|
||||
visible: {
|
||||
get() {
|
||||
return !this.hidden;
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('remove', this.hidden);
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
unpin(){
|
||||
@@ -142,8 +150,14 @@ export default {
|
||||
this.isLoading = false;
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const { actions } = useCachedWidgetLoader();
|
||||
return {
|
||||
loadWidget: actions.load
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
this.widget = await CachedWidgetLoader.loadWidget(this.id);
|
||||
this.widget = await this.loadWidget(this.id);
|
||||
let component = (await import(this.widget.setup.file)).default;
|
||||
this.$options.components["widget" + this.widget.widget_id] = component;
|
||||
this.component = "widget" + this.widget.widget_id;
|
||||
@@ -185,7 +199,7 @@ export default {
|
||||
</a>
|
||||
<Transition>
|
||||
<div v-if="!custom && editMode" class="col-auto px-1 form-switch">
|
||||
<input class="form-check-input ms-0" type="checkbox" role="switch" aria-label="toggle widget" id="flexSwitchCheckChecked" :checked="!hidden" @input="$emit('remove', hidden)">
|
||||
<input class="form-check-input ms-0" type="checkbox" role="switch" aria-label="toggle widget" id="flexSwitchCheckChecked" v-model="visible" :value="true">
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import BsConfirm from "../Bootstrap/Confirm.js";
|
||||
import DropGrid from '../Drop/Grid.js'
|
||||
import DashboardItem from "./Item.js";
|
||||
import CachedWidgetLoader from "../../composables/Dashboard/CachedWidgetLoader.js";
|
||||
import { useCachedWidgetLoader } from "../../composables/Dashboard/CachedWidgetLoader.js";
|
||||
import WidgetIcon from "./Widget/WidgetIcon.js"
|
||||
|
||||
export default {
|
||||
@@ -125,23 +125,23 @@ export default {
|
||||
},
|
||||
checkResizeLimit(item, w, h) {
|
||||
// NOTE(chris): widgets needs to be loaded for this to work
|
||||
let widget = CachedWidgetLoader.getWidget(item.widget);
|
||||
let widget = this.widgetState[item.widget];
|
||||
if (widget) {
|
||||
let minmaxW = widget.setup.width;
|
||||
let minmaxW = { ...widget.setup.width };
|
||||
if (minmaxW.max)
|
||||
minmaxW.min = minmaxW.min || 1;
|
||||
else
|
||||
minmaxW = {min:minmaxW,max:minmaxW};
|
||||
minmaxW = { min: minmaxW, max: minmaxW };
|
||||
if (w < minmaxW.min)
|
||||
w = minmaxW.min;
|
||||
if (w > minmaxW.max)
|
||||
w = minmaxW.max;
|
||||
|
||||
let minmaxH = widget.setup.height;
|
||||
let minmaxH = { ...widget.setup.height };
|
||||
if (minmaxH.max)
|
||||
minmaxH.min = minmaxH.min || 1;
|
||||
else
|
||||
minmaxH = {min:minmaxH,max:minmaxH};
|
||||
minmaxH = { min: minmaxH, max: minmaxH };
|
||||
if (h < minmaxH.min)
|
||||
h = minmaxH.min;
|
||||
if (h > minmaxH.max)
|
||||
@@ -151,7 +151,7 @@ export default {
|
||||
},
|
||||
removeWidget(item, revert) {
|
||||
if (item.custom) {
|
||||
BsConfirm.popup('Are you sure you want to delete this widget?').then(() => this.$emit('widgetRemove', this.name, item.id));
|
||||
BsConfirm.popup(this.$p.t('dashboard', 'alert_deleteWidget')).then(() => this.$emit('widgetRemove', this.name, item.id));
|
||||
} else {
|
||||
let update = {};
|
||||
update[item.id] = { hidden: !revert };
|
||||
@@ -199,6 +199,13 @@ export default {
|
||||
this.$emit('widgetUpdate', this.name, payload);
|
||||
}
|
||||
},
|
||||
setup() {
|
||||
const { state: widgetState } = useCachedWidgetLoader();
|
||||
|
||||
return {
|
||||
widgetState
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
let self = this;
|
||||
let cont = self.$refs.container;
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
import {CoreFilterCmpt} from "../filter/Filter.js";
|
||||
import {CoreNavigationCmpt} from "../navigation/Navigation.js";
|
||||
import FormInput from "../Form/Input.js";
|
||||
import FerienModal from "./Modal.js";
|
||||
|
||||
import ApiFerienverwaltung from '../../api/factory/ferienverwaltung/ferienverwaltung.js';
|
||||
|
||||
export default {
|
||||
name: "Ferienverwaltung",
|
||||
components: {
|
||||
CoreFilterCmpt,
|
||||
CoreNavigationCmpt,
|
||||
FormInput,
|
||||
FerienModal
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
filterVonDatum: null,
|
||||
filterBisDatum: null,
|
||||
loading: false,
|
||||
sideMenuEntries: {},
|
||||
headerMenuEntries: {},
|
||||
tabulatorOptions: {
|
||||
ajaxURL: 'dummy',
|
||||
ajaxRequestFunc: () => this.$api.call(
|
||||
ApiFerienverwaltung.getFerien(this.filterVonDatum, this.filterBisDatum)
|
||||
),
|
||||
ajaxResponse: (url, params, response) => response.data,
|
||||
columns: [
|
||||
{title:"Ferien Id", field:"ferien_id", visible: false, headerFilter: true},
|
||||
{
|
||||
title:"Datum von",
|
||||
field:"vondatum",
|
||||
headerFilter: true,
|
||||
formatter: function (cell) {
|
||||
const dateStr = cell.getValue();
|
||||
if (!dateStr) return "";
|
||||
|
||||
const date = new Date(dateStr);
|
||||
return date.toLocaleString("de-DE", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
hour12: false
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
title:"Datum bis",
|
||||
field:"bisdatum",
|
||||
headerFilter: true,
|
||||
formatter: function (cell) {
|
||||
const dateStr = cell.getValue();
|
||||
if (!dateStr) return "";
|
||||
|
||||
const date = new Date(dateStr);
|
||||
return date.toLocaleString("de-DE", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
hour12: false
|
||||
});
|
||||
}
|
||||
},
|
||||
{title:"Bezeichnung", field:"bezeichnung", headerFilter: true},
|
||||
{title:"Organisationseinheit Kurzbezeichnung", field:"oe_kurzbz", visible: false, headerFilter: true},
|
||||
{title:"Organisationseinheit", field:"oe_bezeichnung", headerFilter: true},
|
||||
{title:"Studienplan", field:"studienplan_bezeichnung", visible: false, headerFilter: true},
|
||||
{title:"Ferientyp Kurzbezeichnung", field:"ferientyp_kurzbz", visible: false, headerFilter: true},
|
||||
{
|
||||
title:"Mitarbeiterrelevant",
|
||||
field:"mitarbeiterrelevant",
|
||||
visible: false,
|
||||
headerFilter: true,
|
||||
hozAlign: "center",
|
||||
formatter:'tickCross', formatterParams: {
|
||||
tickElement: '<i class="fas fa-check text-success"></i>',
|
||||
crossElement: '<i class="fas fa-times text-danger"></i>'
|
||||
},
|
||||
headerFilter:"tickCross", headerFilterParams: {
|
||||
"tristate":true, elementAttributes:{"value":"true"}
|
||||
},
|
||||
headerFilterEmptyCheck:function(value){return value === null}
|
||||
},
|
||||
{
|
||||
title:"Studierendenrelevant",
|
||||
field:"studierendenrelevant",
|
||||
visible: false,
|
||||
headerFilter: true,
|
||||
hozAlign: "center",
|
||||
formatter:'tickCross', formatterParams: {
|
||||
tickElement: '<i class="fas fa-check text-success"></i>',
|
||||
crossElement: '<i class="fas fa-times text-danger"></i>'
|
||||
},
|
||||
headerFilter:"tickCross", headerFilterParams: {
|
||||
"tristate":true, elementAttributes:{"value":"true"}
|
||||
},
|
||||
headerFilterEmptyCheck:function(value){return value === null}
|
||||
},
|
||||
{
|
||||
title:"Lehre planbar",
|
||||
field:"lehre",
|
||||
visible: false,
|
||||
headerFilter: true,
|
||||
hozAlign: "center",
|
||||
formatter:'tickCross', formatterParams: {
|
||||
tickElement: '<i class="fas fa-check text-success"></i>',
|
||||
crossElement: '<i class="fas fa-times text-danger"></i>'
|
||||
},
|
||||
headerFilter:"tickCross", headerFilterParams: {
|
||||
"tristate":true, elementAttributes:{"value":"true"}
|
||||
},
|
||||
headerFilterEmptyCheck:function(value){return value === null}
|
||||
},
|
||||
{title:"Aktionen", field: "actions",
|
||||
minWidth: 150, // Ensures Action-buttons will be always fully displayed
|
||||
formatter: (cell, formatterParams, onRendered) => {
|
||||
let container = document.createElement('div');
|
||||
container.className = "d-flex gap-2";
|
||||
|
||||
let button = document.createElement('button');
|
||||
button.className = 'btn btn-outline-secondary btn-action';
|
||||
button.innerHTML = '<i class="fa fa-edit"></i>';
|
||||
button.title = this.$p.t('person', 'ferien_edit');
|
||||
button.addEventListener('click', (event) =>
|
||||
this.$refs.modal.open(JSON.parse(JSON.stringify(cell.getData()))) // deep copy
|
||||
);
|
||||
container.append(button);
|
||||
|
||||
button = document.createElement('button');
|
||||
button.className = 'btn btn-outline-secondary';
|
||||
button.innerHTML = '<i class="fa fa-trash"></i>';
|
||||
button.addEventListener('click', evt => {
|
||||
evt.stopPropagation();
|
||||
this.$fhcAlert
|
||||
.confirmDelete()
|
||||
.then(result => result ? cell.getData().ferien_id : Promise.reject({handled:true}))
|
||||
.then(ferien_id => this.$api.call(ApiFerienverwaltung.delete(ferien_id)))
|
||||
.then(() => {
|
||||
//cell.getRow().delete();
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
|
||||
this.reload();
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
});
|
||||
container.append(button);
|
||||
|
||||
return container;
|
||||
},
|
||||
frozen: true
|
||||
}
|
||||
]
|
||||
},
|
||||
tabulatorEvents: [
|
||||
{
|
||||
event: 'tableBuilt',
|
||||
handler: async () => {
|
||||
|
||||
//await this.$p.loadCategory(['ferien', 'ui']);
|
||||
await this.$p.loadCategory(['global', 'ferien']);
|
||||
|
||||
let cm = this.$refs.table.tabulator.columnManager;
|
||||
|
||||
cm.getColumnByField('ferien_id').component.updateDefinition({
|
||||
title: this.$p.t('ferien', 'ferienId'),
|
||||
});
|
||||
cm.getColumnByField('vondatum').component.updateDefinition({
|
||||
title: this.$p.t('ferien', 'vondatum'),
|
||||
});
|
||||
cm.getColumnByField('bisdatum').component.updateDefinition({
|
||||
title: this.$p.t('ferien', 'bisdatum'),
|
||||
});
|
||||
cm.getColumnByField('bezeichnung').component.updateDefinition({
|
||||
title: this.$p.t('global', 'bezeichnung'),
|
||||
});
|
||||
cm.getColumnByField('oe_kurzbz').component.updateDefinition({
|
||||
title: this.$p.t('ferien', 'oeKurzbezeichnung'),
|
||||
});
|
||||
cm.getColumnByField('oe_bezeichnung').component.updateDefinition({
|
||||
title: this.$p.t('ferien', 'oeBezeichnung'),
|
||||
});
|
||||
cm.getColumnByField('studienplan_bezeichnung').component.updateDefinition({
|
||||
title: this.$p.t('ferien', 'studienplanBezeichnung'),
|
||||
});
|
||||
cm.getColumnByField('ferientyp_kurzbz').component.updateDefinition({
|
||||
title: this.$p.t('ferien', 'ferientypKurzbz'),
|
||||
});
|
||||
cm.getColumnByField('mitarbeiterrelevant').component.updateDefinition({
|
||||
title: this.$p.t('ferien', 'mitarbeiterrelevant'),
|
||||
});
|
||||
cm.getColumnByField('studierendenrelevant').component.updateDefinition({
|
||||
title: this.$p.t('ferien', 'studierendenrelevant'),
|
||||
});
|
||||
cm.getColumnByField('lehre').component.updateDefinition({
|
||||
title: this.$p.t('ferien', 'lehrePlanbar'),
|
||||
});
|
||||
cm.getColumnByField('actions').component.updateDefinition({
|
||||
title: this.$p.t('global', 'aktionen')
|
||||
});
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
methods: {
|
||||
reload() {
|
||||
this.$refs.table.reloadTable();
|
||||
},
|
||||
actionNew() {
|
||||
this.$refs.modal.open();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
this.$api
|
||||
.call(ApiFerienverwaltung.getDefaultVonBis())
|
||||
.then(result => {
|
||||
this.filterVonDatum = result.data.defaultVon;
|
||||
this.filterBisDatum = result.data.defaultBis;
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
if (error)
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
});
|
||||
},
|
||||
template: `
|
||||
|
||||
<core-navigation-cmpt
|
||||
v-bind:add-side-menu-entries="sideMenuEntries"
|
||||
v-bind:add-header-menu-entries="headerMenuEntries"
|
||||
>
|
||||
</core-navigation-cmpt>
|
||||
|
||||
<div class="h-100 d-flex flex-column">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-5">
|
||||
<form-input
|
||||
type="DatePicker"
|
||||
v-model="filterVonDatum"
|
||||
name="filtervondatum"
|
||||
:label="$p.t('ferien/vondatum')"
|
||||
:enable-time-picker="false"
|
||||
text-input
|
||||
format="dd.MM.yyyy"
|
||||
auto-apply
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="col-5">
|
||||
<form-input
|
||||
type="DatePicker"
|
||||
v-model="filterBisDatum"
|
||||
name="filterbisdatum"
|
||||
:label="$p.t('ferien/bisdatum')"
|
||||
:enable-time-picker="false"
|
||||
text-input
|
||||
format="dd.MM.yyyy"
|
||||
auto-apply
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="col-1 align-self-end">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
@click="reload()"
|
||||
:disabled="loading"
|
||||
>
|
||||
<i v-if="loading" class="fa fa-spinner fa-spin"></i>
|
||||
{{ $p.t('ui/anzeigen') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
<core-filter-cmpt
|
||||
ref="table"
|
||||
table-only
|
||||
:side-menu="false"
|
||||
:tabulator-options="tabulatorOptions"
|
||||
:tabulator-events="tabulatorEvents"
|
||||
reload
|
||||
:reload-btn-infotext="this.$p.t('table', 'reload')"
|
||||
new-btn-show
|
||||
:new-btn-label="$p.t('ui/neu')"
|
||||
@click:new="actionNew"
|
||||
>
|
||||
</core-filter-cmpt>
|
||||
<ferien-modal ref="modal" @saved="reload"></ferien-modal>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
};
|
||||
@@ -0,0 +1,190 @@
|
||||
import BsModal from "../Bootstrap/Modal.js";
|
||||
import BsConfirm from "../Bootstrap/Confirm.js";
|
||||
import CoreForm from "../Form/Form.js";
|
||||
import FormValidation from "../Form/Validation.js";
|
||||
import FormInput from "../Form/Input.js";
|
||||
|
||||
import ApiFerien from '../../api/factory/ferienverwaltung/ferienverwaltung.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BsModal,
|
||||
CoreForm,
|
||||
FormValidation,
|
||||
FormInput
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
oeList: [],
|
||||
studienplaeneList: [],
|
||||
ferientypList: [],
|
||||
loading: false,
|
||||
data: {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
methods: {
|
||||
save() {
|
||||
this.$refs.form.clearValidation();
|
||||
this.loading = true;
|
||||
|
||||
let saveFunc = this.data.ferien_id ? ApiFerien.update : ApiFerien.insert;
|
||||
|
||||
this.$refs.form
|
||||
.call(saveFunc(this.data))
|
||||
.then(result => {
|
||||
this.$emit('saved', result.data);
|
||||
this.loading = false;
|
||||
this.$refs.modal.hide();
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui/gespeichert'));
|
||||
})
|
||||
.catch(error => {
|
||||
if (error)
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
open(data) {
|
||||
this.$refs.form.clearValidation();
|
||||
this.data = data ?? {
|
||||
oe_kurzbz: null,
|
||||
bezeichnung: '',
|
||||
vondatum: null,
|
||||
bisdatum: null,
|
||||
studienplan_id: null
|
||||
};
|
||||
|
||||
this.$api
|
||||
.call(ApiFerien.getOe())
|
||||
.then(result => {
|
||||
this.oeList = result.data;
|
||||
//this.loading = false;
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
if (error)
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
//this.loading = false;
|
||||
});
|
||||
|
||||
|
||||
this.getStudienplaene();
|
||||
|
||||
this.$api
|
||||
.call(ApiFerien.getFerientypen())
|
||||
.then(result => {
|
||||
this.ferientypList = result.data;
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
if (error)
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
});
|
||||
|
||||
this.$refs.modal.show();
|
||||
},
|
||||
getStudienplaene() {
|
||||
if (!this.data.oe_kurzbz) return;
|
||||
|
||||
this.$api
|
||||
.call(ApiFerien.getStudienplaene(this.data.oe_kurzbz, this.data.vondatum, this.data.bisdatum))
|
||||
.then(result => {
|
||||
this.studienplaeneList = result.data;
|
||||
}
|
||||
)
|
||||
.catch(error => {
|
||||
if (error)
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
});
|
||||
},
|
||||
preventCloseOnLoading(ev) {
|
||||
if (this.loading)
|
||||
ev.returnValue = false;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<core-form ref="form" class="stv-details-ferien-edit" @submit.prevent="save">
|
||||
<bs-modal ref="modal" @hide-bs-modal="preventCloseOnLoading">
|
||||
<form-validation></form-validation>
|
||||
|
||||
<fieldset :disabled="loading">
|
||||
<form-input
|
||||
type="DatePicker"
|
||||
v-model="data.vondatum"
|
||||
name="vondatum"
|
||||
:label="$p.t('ferien/vondatum')"
|
||||
:enable-time-picker="false"
|
||||
text-input
|
||||
format="dd.MM.yyyy"
|
||||
auto-apply
|
||||
>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
type="DatePicker"
|
||||
v-model="data.bisdatum"
|
||||
name="bisdatum"
|
||||
:label="$p.t('ferien/bisdatum')"
|
||||
:enable-time-picker="false"
|
||||
text-input
|
||||
format="dd.MM.yyyy"
|
||||
auto-apply
|
||||
>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
v-model="data.bezeichnung"
|
||||
name="bezeichnung"
|
||||
:label="$p.t('global/bezeichnung')"
|
||||
>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
type="select"
|
||||
v-model="data.oe_kurzbz"
|
||||
name="oe_kurzbz"
|
||||
:label="$p.t('ferien/organisationseinheit')"
|
||||
@change="getStudienplaene"
|
||||
>
|
||||
<option :value="null">-- {{ $p.t('ui/alle') }} --</option>
|
||||
<option v-for="oe in oeList" :key="oe.oe_kurzbz" :value="oe.oe_kurzbz">
|
||||
{{ oe.organisationseinheittyp_kurzbz + ' ' + oe.bezeichnung }}
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
type="select"
|
||||
v-model="data.studienplan_id"
|
||||
name="studienplan_id"
|
||||
:label="$p.t('ferien/studienplan')"
|
||||
>
|
||||
<option :value="null">-- {{ $p.t('ui/keineAuswahl') }} --</option>
|
||||
<option v-for="studienplan in studienplaeneList" :key="studienplan.studienplan_id" :value="studienplan.studienplan_id">
|
||||
{{ studienplan.bezeichnung }}
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
type="select"
|
||||
v-model="data.ferientyp_kurzbz"
|
||||
name="ferientyp_kurzbz"
|
||||
:label="$p.t('ferien/ferientypKurzbz')"
|
||||
>
|
||||
<option :value="null">-- {{ $p.t('ui/keineAuswahl') }} --</option>
|
||||
<option v-for="ferientyp in ferientypList" :key="ferientyp.ferientyp_kurzbz" :value="ferientyp.ferientyp_kurzbz">
|
||||
{{ ferientyp.ferientyp_kurzbz }}
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
</fieldset>
|
||||
|
||||
<template #footer>
|
||||
<button type="submit" class="btn btn-primary" :disabled="loading">
|
||||
<i v-if="loading" class="fa fa-spinner fa-spin"></i>
|
||||
{{ $p.t('ui/speichern') }}
|
||||
</button>
|
||||
</template>
|
||||
</bs-modal>
|
||||
</core-form>`
|
||||
};
|
||||
@@ -170,6 +170,7 @@ export default {
|
||||
return this.$attrs.modelValue;
|
||||
},
|
||||
set(v) {
|
||||
this.clearValidationForThisName()
|
||||
if (!this.$attrs.hasOwnProperty('modelValue'))
|
||||
this.modelValueDummy = v;
|
||||
this.$emit('update:modelValue', v);
|
||||
@@ -242,9 +243,9 @@ export default {
|
||||
template: `
|
||||
<component :is="!hasContainer ? 'FhcFragment' : 'div'" class="position-relative" :class="autoContainerClass">
|
||||
<label v-if="label && lcType != 'radio' && lcType != 'checkbox'" :class="!noAutoClass && 'form-label'" :for="idCmp">{{label}}</label>
|
||||
<input v-if="tag == 'input'" :type="lcType" ref="input" v-model="modelValueCmp" v-bind="$attrs" :id="idCmp" :name="name" :class="validationClass" :modelValue="undefined" @input="clearValidationForThisName(); $emit('input', $event)">
|
||||
<textarea v-else-if="tag == 'textarea'" ref="input" v-model="modelValueCmp" v-bind="$attrs" :id="idCmp" :name="name" :class="validationClass" :modelValue="undefined" @input="clearValidationForThisName(); $emit('input', $event)"></textarea>
|
||||
<select v-else-if="tag == 'select'" ref="input" v-model="modelValueCmp" v-bind="$attrs" :id="idCmp" :name="name" :class="validationClass" :modelValue="undefined" @input="clearValidationForThisName(); $emit('input', $event)">
|
||||
<input v-if="tag == 'input'" :type="lcType" ref="input" v-model="modelValueCmp" v-bind="$attrs" :id="idCmp" :name="name" :class="validationClass" :modelValue="undefined" @input="$emit('input', $event)">
|
||||
<textarea v-else-if="tag == 'textarea'" ref="input" v-model="modelValueCmp" v-bind="$attrs" :id="idCmp" :name="name" :class="validationClass" :modelValue="undefined" @input="$emit('input', $event)"></textarea>
|
||||
<select v-else-if="tag == 'select'" ref="input" v-model="modelValueCmp" v-bind="$attrs" :id="idCmp" :name="name" :class="validationClass" :modelValue="undefined" @input="$emit('input', $event)">
|
||||
<slot></slot>
|
||||
</select>
|
||||
<component
|
||||
|
||||
@@ -63,7 +63,7 @@ export default {
|
||||
const vm = this;
|
||||
tinymce.init({
|
||||
target: this.$refs.editor.$refs.input, //Important: not selector: to enable multiple import of component
|
||||
//height: 800,
|
||||
min_height: 300,
|
||||
//plugins: ['lists'],
|
||||
toolbar: 'styleselect | bold italic underline | alignleft aligncenter alignright alignjustify | link',
|
||||
plugins: 'link',
|
||||
@@ -133,6 +133,7 @@ export default {
|
||||
return this.$api
|
||||
.call(ApiMessages.getDataVorlage(vorlage_kurzbz))
|
||||
.then(response => {
|
||||
this.editor.setContent(response.data.text);
|
||||
this.formData.body = response.data.text;
|
||||
this.formData.subject = response.data.subject;
|
||||
}).catch(this.$fhcAlert.handleSystemError);
|
||||
@@ -203,24 +204,6 @@ export default {
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'formData.body': {
|
||||
handler(newVal) {
|
||||
const tinymcsVal = this.editor.getContent();
|
||||
|
||||
if (newVal && tinymcsVal != newVal) {
|
||||
//Inhalt des Editors aktualisieren
|
||||
this.editor.setContent(newVal);
|
||||
}
|
||||
}
|
||||
},
|
||||
'formData.vorlage_kurzbz': {
|
||||
handler(newVal){
|
||||
if (newVal && newVal != null) {
|
||||
this.formData.subject = newVal;
|
||||
return this.getDataVorlage(newVal);
|
||||
}
|
||||
}
|
||||
},
|
||||
messageId: {
|
||||
immediate: true,
|
||||
handler: async function (newMessageId) {
|
||||
@@ -231,6 +214,7 @@ export default {
|
||||
this.replyData = result.data;
|
||||
|
||||
if (this.replyData.length > 0) {
|
||||
this.editor.setContent(this.replyData[0].replyBody);
|
||||
this.formData.subject = this.replyData[0].replySubject;
|
||||
this.formData.body = this.replyData[0].replyBody;
|
||||
this.formData.relationmessage_id = newMessageId;
|
||||
@@ -290,19 +274,6 @@ export default {
|
||||
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
//case of reply
|
||||
if(this.messageId) {
|
||||
this.$api
|
||||
.call(ApiMessages.getReplyData(this.messageId))
|
||||
.then(result => {
|
||||
this.replyData = result.data;
|
||||
this.formData.subject = this.replyData[0].replySubject;
|
||||
this.formData.body = this.replyData[0].replyBody;
|
||||
this.formData.relationmessage_id = this.messageId;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.initTinyMCE();
|
||||
@@ -342,7 +313,7 @@ export default {
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-8">
|
||||
<form-form class="row g-3 mt-2 h-100" ref="formMessage">
|
||||
<form-form class="row g-3 mt-2 align-content-start" ref="formMessage">
|
||||
|
||||
<div class="row mb-3">
|
||||
|
||||
@@ -367,7 +338,7 @@ export default {
|
||||
</div>
|
||||
|
||||
<!--Tiny MCE-->
|
||||
<div class="row mb-3 h-100 tiny-90">
|
||||
<div class="row mb-3 tiny-90">
|
||||
<form-input
|
||||
ref="editor"
|
||||
:label="$p.t('global','nachricht') + ' *'"
|
||||
|
||||
@@ -62,9 +62,18 @@ export default {
|
||||
const vm = this;
|
||||
tinymce.init({
|
||||
target: this.$refs.editor.$refs.input, //Important: not selector: to enable multiple import of component
|
||||
//height: 800,
|
||||
min_height: 300,
|
||||
//plugins: ['lists'],
|
||||
toolbar: 'styleselect | bold italic underline | alignleft aligncenter alignright alignjustify',
|
||||
toolbar: 'styleselect | bold italic underline | alignleft aligncenter alignright alignjustify | link',
|
||||
plugins: 'link',
|
||||
link_context_toolbar: true,
|
||||
automatic_uploads: true,
|
||||
default_link_target: "_blank",
|
||||
link_title: true,
|
||||
target_list: [
|
||||
{ title: 'New tab', value: '_blank' },
|
||||
{ title: 'Same tab', value: '_self' }
|
||||
],
|
||||
style_formats: [
|
||||
{title: 'Blocks', block: 'div'},
|
||||
{title: 'Paragraph', block: 'p'},
|
||||
@@ -98,7 +107,8 @@ export default {
|
||||
return this.$api
|
||||
.call(ApiMessages.sendMessage(this.typeId, data))
|
||||
.then(response => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSent'));
|
||||
if(this.openMode == "inSamePage")
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSent'));
|
||||
this.hideTemplate();
|
||||
this.resetForm();
|
||||
this.messageSent = true;
|
||||
@@ -114,19 +124,17 @@ export default {
|
||||
return this.$api
|
||||
.call(ApiMessages.getDataVorlage(vorlage_kurzbz))
|
||||
.then(response => {
|
||||
this.editor.setContent(response.data.text);
|
||||
this.formData.body = response.data.text;
|
||||
this.formData.subject = response.data.subject;
|
||||
}).catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
getPreviewText(){
|
||||
console.log("subj" + this.formData.subject);
|
||||
const data = new FormData();
|
||||
|
||||
data.append('data', JSON.stringify(this.formData.body));
|
||||
data.append('ids', JSON.stringify(this.id));
|
||||
|
||||
console.log("subj" + this.formData.subject);
|
||||
|
||||
return this.$api
|
||||
.call(ApiMessages.getPreviewText(
|
||||
this.typeId, data))
|
||||
@@ -195,6 +203,7 @@ export default {
|
||||
.call(ApiMessages.getReplyData(messageId))
|
||||
.then(result => {
|
||||
this.replyData = result.data;
|
||||
this.editor.setContent(this.replyData[0].replyBody);
|
||||
this.formData.subject = this.replyData[0].replySubject;
|
||||
this.formData.body = this.replyData[0].replyBody;
|
||||
this.formData.relationmessage_id = messageId;
|
||||
@@ -202,27 +211,6 @@ export default {
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'formData.body': {
|
||||
handler(newVal) {
|
||||
const tinymcsVal = this.editor.getContent();
|
||||
|
||||
if (newVal && tinymcsVal != newVal) {
|
||||
//Inhalt des Editors aktualisieren
|
||||
this.editor.setContent(newVal);
|
||||
}
|
||||
}
|
||||
},
|
||||
'formData.vorlage_kurzbz': {
|
||||
handler(newVal){
|
||||
|
||||
if (newVal && newVal != null) {
|
||||
this.formData.subject = newVal;
|
||||
return this.getDataVorlage(newVal);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
created(){
|
||||
const missingparamsmsgs = [];
|
||||
if(!this.typeId)
|
||||
@@ -291,17 +279,8 @@ export default {
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
//case of reply
|
||||
if(this.messageId != null) {
|
||||
if(this.messageId) {
|
||||
this.loadReplyData(this.messageId);
|
||||
/* this.$api
|
||||
.call(ApiMessages.getReplyData(this.messageId))
|
||||
.then(result => {
|
||||
this.replyData = result.data;
|
||||
this.formData.subject = this.replyData[0].replySubject;
|
||||
this.formData.body = this.replyData[0].replyBody;
|
||||
this.formData.relationmessage_id = this.messageId;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);*/
|
||||
}
|
||||
|
||||
},
|
||||
@@ -499,10 +478,10 @@ export default {
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6" style="border-right: 1px">
|
||||
You can safely close this window.
|
||||
You can safely close this window/tab.
|
||||
</div>
|
||||
<div class="col-6">
|
||||
Sie können dieses Fenster schließen.
|
||||
Fenster/Reiter kann geschlossen werden!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,6 +30,7 @@ export default {
|
||||
personId: null,
|
||||
layoutColumnsOnNewData: false,
|
||||
height: '400',
|
||||
arePhrasesLoaded: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -65,7 +66,14 @@ export default {
|
||||
buildTreemap(messages) {
|
||||
if (!messages || !messages.data || messages.data.length === 0)
|
||||
{
|
||||
return {data: [], last_page: 0};
|
||||
if(this.tabulatorOptions.pagination)
|
||||
{
|
||||
return {data: [], last_page: 0};
|
||||
}
|
||||
else
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
const last_page = messages.meta.count;
|
||||
@@ -106,7 +114,15 @@ export default {
|
||||
// to avoid endless loop
|
||||
if (iteration > messages.length) break;
|
||||
}
|
||||
return {data: messageNested, last_page: last_page};
|
||||
|
||||
if(this.tabulatorOptions.pagination)
|
||||
{
|
||||
return {data: messageNested, last_page: last_page};
|
||||
}
|
||||
else
|
||||
{
|
||||
return messageNested;
|
||||
}
|
||||
},
|
||||
loadAjaxCall(url, config, params){
|
||||
return this.$api.call(
|
||||
@@ -180,7 +196,7 @@ export default {
|
||||
],
|
||||
formatter: (cell, formatterParams) => {
|
||||
const key = formatterParams[cell.getValue()];
|
||||
return this.$p.t('messages', key);
|
||||
return this.$p?.t?.('messages', key) || key;
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -252,7 +268,7 @@ export default {
|
||||
frozen: true
|
||||
}
|
||||
],
|
||||
pagination: true,
|
||||
pagination: false,
|
||||
paginationMode: "remote",
|
||||
paginationSize: 15,
|
||||
paginationInitialPage: 1,
|
||||
@@ -290,8 +306,6 @@ export default {
|
||||
{
|
||||
event: 'tableBuilt',
|
||||
handler: async() => {
|
||||
await this.$p.loadCategory(['global', 'person', 'stv', 'messages', 'ui', 'notiz']);
|
||||
|
||||
const setHeader = (field, text) => {
|
||||
const col = this.$refs.table.tabulator.getColumn(field);
|
||||
if (!col) return;
|
||||
@@ -342,6 +356,12 @@ export default {
|
||||
});*/
|
||||
},
|
||||
created(){
|
||||
this.$p
|
||||
.loadCategory(['global', 'person', 'stv', 'messages', 'ui', 'notiz'])
|
||||
.then(() => {
|
||||
this.arePhrasesLoaded = true;
|
||||
});
|
||||
|
||||
if(this.typeId != 'person_id' && Array.isArray(this.id) && this.id.length === 1) {
|
||||
const params = {
|
||||
id: this.id,
|
||||
@@ -366,6 +386,7 @@ export default {
|
||||
<!--table-->
|
||||
<div class="col-sm-6 pt-1">
|
||||
<core-filter-cmpt
|
||||
v-if="arePhrasesLoaded"
|
||||
ref="table"
|
||||
:tabulator-options="tabulatorOptions"
|
||||
:tabulator-events="tabulatorEvents"
|
||||
@@ -398,6 +419,7 @@ export default {
|
||||
<div class="col-sm-12 pt-6">
|
||||
<core-filter-cmpt
|
||||
ref="table"
|
||||
v-if="arePhrasesLoaded"
|
||||
:tabulator-options="tabulatorOptions"
|
||||
:tabulator-events="tabulatorEvents"
|
||||
table-only
|
||||
|
||||
@@ -82,14 +82,16 @@ export default {
|
||||
this.$refs.modalMsg.show();
|
||||
}
|
||||
else if (this.openMode == "inSamePage"){
|
||||
console.log("in same Page");
|
||||
this.isVisibleDiv = true;
|
||||
if(messageId)
|
||||
this.$refs.templateNewDivMessage.loadReplyData(messageId);
|
||||
else
|
||||
this.$refs.templateNewDivMessage.resetForm();
|
||||
|
||||
this.$refs.templateNewDivMessage.showTemplate();
|
||||
this.$nextTick(() => {
|
||||
if(messageId)
|
||||
this.$refs.templateNewDivMessage.loadReplyData(messageId);
|
||||
else
|
||||
this.$refs.templateNewDivMessage.resetForm();
|
||||
|
||||
this.$refs.templateNewDivMessage.showTemplate();
|
||||
});
|
||||
}
|
||||
else
|
||||
console.log("no valid openMode");
|
||||
|
||||
@@ -74,6 +74,24 @@ export default {
|
||||
],
|
||||
'abschlussdokument_lehrgaenge.xml.php': [
|
||||
'AbschlussdokumentLehrgaenge'
|
||||
],
|
||||
'microcredential.xml.php' : [
|
||||
'microcredentialzertifikat_1',
|
||||
'microcredentialzertifikat_2',
|
||||
'microcredentialzertifikat_3',
|
||||
'microcredentialzertifikat_4',
|
||||
'microcredential_1',
|
||||
'microcredential_2',
|
||||
'microcredential_3',
|
||||
'microcredential_4',
|
||||
'microdegree_1',
|
||||
'microdegree_2',
|
||||
'microdegree_3',
|
||||
'microdegree_4',
|
||||
'microdegreeabschluss_1',
|
||||
'microdegreeabschluss_2',
|
||||
'microdegreeabschluss_3',
|
||||
'microdegreeabschluss_4',
|
||||
]
|
||||
},
|
||||
documentDropdownObject: {}
|
||||
|
||||
@@ -83,6 +83,8 @@ export default {
|
||||
});
|
||||
},
|
||||
open() {
|
||||
|
||||
this.getBuchungstypen(this.currentSemester);
|
||||
this.data = {
|
||||
buchungstyp_kurzbz: '',
|
||||
betrag: '-0.00',
|
||||
@@ -105,7 +107,7 @@ export default {
|
||||
const text = typ.standardtext || '';
|
||||
const creditpoints = typ.credit_points || '';
|
||||
|
||||
if (!this.data.betrag || this.data.betrag == '-0.00')
|
||||
if (!this.data.betrag || this.data.betrag == '-0.00' || this.data.betrag !== amount)
|
||||
this.data.betrag = amount;
|
||||
|
||||
if (!this.data.buchungstext)
|
||||
@@ -113,7 +115,18 @@ export default {
|
||||
|
||||
if (this.config.showCreditpoints && (this.data.credit_points == '0.00' || this.data.credit_points === null))
|
||||
this.data.credit_points = creditpoints;
|
||||
}
|
||||
},
|
||||
getBuchungstypen(studiensemester_kurzbz)
|
||||
{
|
||||
this.$api
|
||||
.call(ApiKonto.getBuchungstypen(studiensemester_kurzbz))
|
||||
.then(result => {
|
||||
this.lists.buchungstypen = result.data;
|
||||
if (this.data.buchungstyp_kurzbz)
|
||||
this.checkDefaultBetrag(this.data.buchungstyp_kurzbz);
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<core-form ref="form" class="stv-details-konto-edit" @submit.prevent="save">
|
||||
@@ -166,6 +179,7 @@ export default {
|
||||
<form-input
|
||||
type="select"
|
||||
v-model="data.studiensemester_kurzbz"
|
||||
@change="getBuchungstypen(data.studiensemester_kurzbz)"
|
||||
name="studiensemester_kurzbz"
|
||||
:label="$p.t('lehre/studiensemester')"
|
||||
>
|
||||
|
||||
@@ -14,6 +14,9 @@ export default {
|
||||
inject: {
|
||||
defaultSemester: {
|
||||
from: 'defaultSemester'
|
||||
},
|
||||
currentSemester: {
|
||||
from: 'currentSemester'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -95,8 +98,9 @@ export default {
|
||||
this.formData.themenbereich = null;
|
||||
this.formData.projekttyp_kurzbz = null;
|
||||
this.formData.firma = null;
|
||||
this.formData.lehrveranstaltung_id = null;
|
||||
this.formData.lehreinheit_id = null;
|
||||
// dont reset these form fields for UX reasons
|
||||
// this.formData.lehrveranstaltung_id = null;
|
||||
// this.formData.lehreinheit_id = null;
|
||||
this.formData.beginn = null;
|
||||
this.formData.ende = null;
|
||||
this.formData.freigegeben = true;
|
||||
@@ -109,7 +113,7 @@ export default {
|
||||
getFormData(newProjektarbeit, studiensemester_kurzbz, additional_lehrveranstaltung_id) {
|
||||
|
||||
this.additional_lehrveranstaltung_id = additional_lehrveranstaltung_id;
|
||||
this.studiensemester = studiensemester_kurzbz || this.defaultSemester;
|
||||
this.studiensemester = studiensemester_kurzbz || this.currentSemester;
|
||||
this.newProjektarbeit = newProjektarbeit;
|
||||
|
||||
this.$api
|
||||
|
||||
@@ -121,7 +121,6 @@ export default {
|
||||
height: 'auto',
|
||||
minHeight: '100',
|
||||
selectableRows: true,
|
||||
selectableRows: 1,
|
||||
index: 'betreuer_id',
|
||||
persistence:{
|
||||
columns: true, //persist column layout
|
||||
|
||||
@@ -41,8 +41,8 @@ export default {
|
||||
),
|
||||
ajaxResponse: (url, params, response) => response.data,
|
||||
columns: [
|
||||
{title: "Typ", field: "type"},
|
||||
{title: "Betrag", field: "betrag",
|
||||
{title: "Typ", field: "type", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
|
||||
{title: "Betrag", field: "betrag", headerFilter: true,
|
||||
formatter: function(cell) {
|
||||
let value = cell.getValue();
|
||||
if (value == null) {
|
||||
@@ -51,14 +51,14 @@ export default {
|
||||
return parseFloat(value).toFixed(2);
|
||||
}
|
||||
},
|
||||
{title: "Bezeichnung", field: "bezeichnung"},
|
||||
{title: "Studiensemester", field: "studiensemester_kurzbz"},
|
||||
{title: "Pruefung_id", field: "pruefung_id", visible: false},
|
||||
{title: "mitarbeiter_uid", field: "mitarbeiter_uid", visible: false},
|
||||
{title: "projektarbeit_id", field: "projektarbeit_id", visible: false},
|
||||
{title: "lehreinheit_id", field: "lehreinheit_id", visible: true},
|
||||
{title: "betreuerart_kurzbz", field: "betreuerart_kurzbz", visible: false},
|
||||
{title: "vertrag_id", field: "vertrag_id", visible: false}, //just for testing
|
||||
{title: "Bezeichnung", field: "bezeichnung", headerFilter: true},
|
||||
{title: "Studiensemester", field: "studiensemester_kurzbz", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
|
||||
{title: "Pruefung_id", field: "pruefung_id", visible: false, headerFilter: true},
|
||||
{title: "mitarbeiter_uid", field: "mitarbeiter_uid", visible: false, headerFilter: true},
|
||||
{title: "projektarbeit_id", field: "projektarbeit_id", visible: false, headerFilter: true},
|
||||
{title: "lehreinheit_id", field: "lehreinheit_id", visible: true, headerFilter: true},
|
||||
{title: "betreuerart_kurzbz", field: "betreuerart_kurzbz", visible: false, headerFilter: true},
|
||||
{title: "vertrag_id", field: "vertrag_id", visible: false, headerFilter: true}, //just for testing
|
||||
{
|
||||
title: 'Aktionen', field: 'actions',
|
||||
minWidth: 50,
|
||||
@@ -110,10 +110,10 @@ export default {
|
||||
],
|
||||
layout: 'fitColumns',
|
||||
layoutColumnsOnNewData: false,
|
||||
height: '200',
|
||||
height: '250',
|
||||
selectableRowsRangeMode: 'click',
|
||||
selectableRows: true,
|
||||
persistenceID: 'core-contracts-details-2026021701'
|
||||
persistenceID: 'core-contracts-details-2026050501'
|
||||
},
|
||||
tabulatorEvents: [
|
||||
{
|
||||
@@ -137,7 +137,7 @@ export default {
|
||||
|
||||
setHeader('type', this.$p.t('global', 'typ'));
|
||||
setHeader('bezeichnung', this.$p.t('ui', 'bezeichnung'));
|
||||
setHeader('lehreinheit_id', this.$p.t('ui', 'lehreinheit_id'));
|
||||
setHeader('lehreinheit_id', this.$p.t('lehre', 'lehreinheit_id'));
|
||||
setHeader('betrag', this.$p.t('ui', 'betrag'));
|
||||
setHeader('studiensemester_kurzbz', this.$p.t('lehre', 'studiensemester'));
|
||||
setHeader('mitarbeiter_uid', this.$p.t('ui', 'mitarbeiter_uid'));
|
||||
|
||||
@@ -47,12 +47,13 @@ export default {
|
||||
this.endpoint.getStatiOfContract(this.person_id, this.vertrag_id)
|
||||
),
|
||||
ajaxResponse: (url, params, response) => response.data,
|
||||
persistenceID: 'core-contracts-status-2026021701',
|
||||
persistenceID: 'core-contracts-status-2026050501',
|
||||
columns: [
|
||||
{title: "Status", field: "bezeichnung"},
|
||||
{title: "Status", field: "bezeichnung", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
|
||||
{
|
||||
title: "Datum",
|
||||
field: "datum",
|
||||
headerFilter: true,
|
||||
formatter: function (cell) {
|
||||
const dateStr = cell.getValue();
|
||||
const date = new Date(dateStr); // Convert to Date object
|
||||
@@ -66,14 +67,15 @@ export default {
|
||||
});
|
||||
}
|
||||
},
|
||||
{title: "vertrag_id", field: "vertrag_id", visible: false},
|
||||
{title: "Vertragsstatus", field: "vertragsstatus_kurzbz", visible: false},
|
||||
{title: "User", field: "mitarbeiter_uid", visible: false},
|
||||
{title: "insertvon", field: "insertvon", visible: false},
|
||||
{title: "vertrag_id", field: "vertrag_id", visible: false, headerFilter: true},
|
||||
{title: "Vertragsstatus", field: "vertragsstatus_kurzbz", visible: false, headerFilter: true},
|
||||
{title: "User", field: "mitarbeiter_uid", visible: false, headerFilter: true},
|
||||
{title: "insertvon", field: "insertvon", visible: false, headerFilter: true},
|
||||
{
|
||||
title: "insertamum",
|
||||
field: "insertamum",
|
||||
visible: false,
|
||||
headerFilter: true,
|
||||
formatter: function (cell) {
|
||||
const dateStr = cell.getValue();
|
||||
const date = new Date(dateStr);
|
||||
@@ -87,11 +89,12 @@ export default {
|
||||
});
|
||||
}
|
||||
},
|
||||
{title: "updatevon", field: "updatevon", visible: false},
|
||||
{title: "updatevon", field: "updatevon", visible: false, headerFilter: true},
|
||||
{
|
||||
title: "updateamum",
|
||||
field: "updateamum",
|
||||
visible: false,
|
||||
headerFilter: true,
|
||||
formatter: function (cell) {
|
||||
const dateStr = cell.getValue();
|
||||
const date = new Date(dateStr);
|
||||
@@ -148,7 +151,7 @@ export default {
|
||||
],
|
||||
layout: 'fitColumns',
|
||||
layoutColumnsOnNewData: false,
|
||||
height: '200',
|
||||
height: '250',
|
||||
selectableRowsRangeMode: 'click',
|
||||
selectableRows: true,
|
||||
},
|
||||
|
||||
@@ -30,10 +30,11 @@ export default {
|
||||
),
|
||||
ajaxResponse: (url, params, response) => response.data,
|
||||
columns: [
|
||||
{title: "Typ", field: "type", width: 100},
|
||||
{title: "Typ", field: "type", width: 100, headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
|
||||
{
|
||||
title: "Betrag",
|
||||
field: "betrag1",
|
||||
headerFilter: true,
|
||||
formatter: function(cell) {
|
||||
let value = cell.getValue();
|
||||
if (value == null) {
|
||||
@@ -41,28 +42,29 @@ export default {
|
||||
}
|
||||
return parseFloat(value).toFixed(2);
|
||||
}},
|
||||
{title: "Bezeichnung", field: "bezeichnung", width: 150},
|
||||
{title: "Studiensemester", field: "studiensemester_kurzbz", width: 160},
|
||||
{title: "mitarbeiter_uid", field: "mitarbeiter_uid", visible: false},
|
||||
{title: "projektarbeit_id", field: "projektarbeit_id", visible: false},
|
||||
{title: "lehreinheit_id", field: "lehreinheit_id", visible: true},
|
||||
{title: "betreuerart_kurzbz", field: "betreuerart_kurzbz", visible: false},
|
||||
{title: "Vertragsstunden", field: "vertragsstunden", visible: false},
|
||||
{title: "vertrag_id", field: "vertrag_id", visible: false}, //just for testing
|
||||
{title: "Bezeichnung", field: "bezeichnung", width: 150, headerFilter: true},
|
||||
{title: "Studiensemester", field: "studiensemester_kurzbz", width: 160, headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
|
||||
{title: "mitarbeiter_uid", field: "mitarbeiter_uid", visible: false, headerFilter: true},
|
||||
{title: "projektarbeit_id", field: "projektarbeit_id", visible: false, headerFilter: true},
|
||||
{title: "lehreinheit_id", field: "lehreinheit_id", visible: true, headerFilter: true},
|
||||
{title: "betreuerart_kurzbz", field: "betreuerart_kurzbz", visible: false, headerFilter: true},
|
||||
{title: "Vertragsstunden", field: "vertragsstunden", visible: false, headerFilter: true},
|
||||
{title: "vertrag_id", field: "vertrag_id", visible: false, headerFilter: true}, //just for testing
|
||||
{
|
||||
title: "VertragsstundenStudiensemester",
|
||||
field: "vertragsstunden_studiensemester_kurzbz",
|
||||
visible: false
|
||||
visible: false,
|
||||
headerFilter: true
|
||||
},
|
||||
],
|
||||
layout: 'fitColumns',
|
||||
layoutColumnsOnNewData: false,
|
||||
height: 150,
|
||||
height: 250,
|
||||
selectableRowsRangeMode: 'click',
|
||||
selectableRows: true,
|
||||
selectableRowsRollingSelection: false, //only allow multiselect with STRG
|
||||
index: "lehreinheit_id",
|
||||
persistenceID: 'core-contracts-unassigned-2026021701'
|
||||
persistenceID: 'core-contracts-unassigned-2026050501'
|
||||
},
|
||||
tabulatorEvents: [
|
||||
{
|
||||
@@ -100,7 +102,7 @@ export default {
|
||||
|
||||
setHeader('type', this.$p.t('global', 'typ'));
|
||||
setHeader('bezeichnung', this.$p.t('ui', 'bezeichnung'));
|
||||
setHeader('lehreinheit_id', this.$p.t('ui', 'lehreinheit_id'));
|
||||
setHeader('lehreinheit_id', this.$p.t('lehre', 'lehreinheit_id'));
|
||||
setHeader('betrag1', this.$p.t('ui', 'betrag'));
|
||||
setHeader('studiensemester_kurzbz', this.$p.t('lehre', 'studiensemester'));
|
||||
setHeader('mitarbeiter_uid', this.$p.t('ui', 'mitarbeiter_uid'));
|
||||
|
||||
@@ -20,9 +20,6 @@ export default {
|
||||
ContractStati
|
||||
},
|
||||
inject: {
|
||||
/* cisRoot: {
|
||||
from: 'cisRoot'
|
||||
},*/
|
||||
hasSchreibrechte: {
|
||||
from: 'hasSchreibrechte',
|
||||
default: false
|
||||
@@ -54,9 +51,9 @@ export default {
|
||||
),
|
||||
ajaxResponse: (url, params, response) => response.data,
|
||||
columns: [
|
||||
{title: "Bezeichnung", field: "bezeichnung", width: 300},
|
||||
{title: "Bezeichnung", field: "bezeichnung", width: 300, headerFilter: true},
|
||||
{
|
||||
title: "Betrag", field: "betrag", width: 100,
|
||||
title: "Betrag", field: "betrag", width: 100, headerFilter: true,
|
||||
formatter: function (cell) {
|
||||
let value = cell.getValue();
|
||||
|
||||
@@ -66,12 +63,13 @@ export default {
|
||||
return parseFloat(value).toFixed(2);
|
||||
}
|
||||
},
|
||||
{title: "Vertragstyp", field: "vertragstyp_bezeichnung", width: 125},
|
||||
{title: "Status", field: "status", width: 100},
|
||||
{title: "Vertragstyp", field: "vertragstyp_bezeichnung", width: 125, headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
|
||||
{title: "Status", field: "status", width: 100, headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
|
||||
{
|
||||
title: "Vertragsdatum",
|
||||
field: "vertragsdatum",
|
||||
width: 128,
|
||||
headerFilter: true,
|
||||
formatter: function (cell) {
|
||||
const dateStr = cell.getValue();
|
||||
const date = new Date(dateStr);
|
||||
@@ -82,11 +80,11 @@ export default {
|
||||
});
|
||||
}
|
||||
},
|
||||
{title: "VertragId", field: "vertrag_id", visible: false},
|
||||
{title: "Vertragsstunden", field: "vertragsstunden", visible: false},
|
||||
{title: "VertragsstundenStudiensemester", field: "vertragsstunden_studiensemester_kurzbz", visible: false},
|
||||
{title: "Anmerkung", field: "anmerkung", visible: false},
|
||||
{title: "isAbgerechnet", field: "isabgerechnet", visible: false},
|
||||
{title: "VertragId", field: "vertrag_id", visible: false, headerFilter: true},
|
||||
{title: "Vertragsstunden", field: "vertragsstunden", visible: false, headerFilter: true},
|
||||
{title: "VertragsstundenStudiensemester", field: "vertragsstunden_studiensemester_kurzbz", visible: false, headerFilter: true},
|
||||
{title: "Anmerkung", field: "anmerkung", visible: false, headerFilter: true},
|
||||
{title: "isAbgerechnet", field: "isabgerechnet", visible: false, headerFilter: true},
|
||||
{
|
||||
title: 'Aktionen', field: 'actions',
|
||||
minWidth: 150,
|
||||
@@ -140,11 +138,13 @@ export default {
|
||||
columns: true,
|
||||
filter: false //to avoids js errors
|
||||
},
|
||||
persistenceID: 'core-contracts-2026021701',
|
||||
persistenceID: 'core-contracts-2026050501',
|
||||
};
|
||||
return options;
|
||||
},
|
||||
tabulatorEvents() {
|
||||
const vm = this;
|
||||
|
||||
const events = [
|
||||
{
|
||||
event: 'tableBuilt',
|
||||
@@ -177,28 +177,11 @@ export default {
|
||||
setHeader('actions', this.$p.t('global', 'aktionen'));
|
||||
}
|
||||
},
|
||||
/* {
|
||||
//is just enabled for ADDON Injection KU: MultiprintHonorarvertrag
|
||||
//(maybe enable also for ADDON FH Burgenland: MultiAccept later)
|
||||
event: 'rowClick',
|
||||
handler: (e, row) => {
|
||||
if (this.dataPrintHonorar != null && this.dataPrintHonorar.multiselect != null) {
|
||||
const selectedContract = row.getData().vertrag_id;
|
||||
const status = row.getData().status;
|
||||
const bezeichnung = row.getData().bezeichnung;
|
||||
|
||||
this.toggleRowClick(selectedContract, status, bezeichnung);
|
||||
}
|
||||
}
|
||||
},*/
|
||||
{
|
||||
event: 'rowClick',
|
||||
handler: (e, row) => {
|
||||
if (!this.dataPrintHonorar?.multiselect) return;
|
||||
|
||||
handler: function (e, row) {
|
||||
const { vertrag_id, status, bezeichnung, vertragstyp_bezeichnung } = row.getData();
|
||||
|
||||
this.toggleRowClick(e, vertrag_id, status, bezeichnung, vertragstyp_bezeichnung);
|
||||
vm.toggleRowClick(e, vertrag_id, status, bezeichnung, vertragstyp_bezeichnung);
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -242,8 +225,6 @@ export default {
|
||||
person_id() {
|
||||
this.$refs.table.reloadTable();
|
||||
this.arraySelectedContracts = [];
|
||||
/* if(this.dataPrintHonorar?.multiselect)
|
||||
this.dataPrintHonorar.multiselect = [];*/
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
@@ -270,7 +251,6 @@ export default {
|
||||
)
|
||||
.then(result => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
|
||||
//window.scrollTo(0, 0);
|
||||
this.reload();
|
||||
this.contractSelected.vertrag_id = null;
|
||||
})
|
||||
@@ -518,19 +498,9 @@ export default {
|
||||
'content/pdfExport.php?xml=' + this.dataPrintHonorar.xml + '&xsl=' + this.dataPrintHonorar.xsl + '&mitarbeiter_uid=' + this.mitarbeiter_uid + vertragString + '&output=pdf&uid=' + this.mitarbeiter_uid;
|
||||
window.open(linkToPdf, '_blank');
|
||||
},
|
||||
/* toggleRowClick(contractId, status, bezeichnung) {
|
||||
const index = this.arraySelectedContracts.findIndex(
|
||||
([id]) => id === contractId
|
||||
);
|
||||
if (index !== -1) {
|
||||
this.arraySelectedContracts.splice(index, 1);
|
||||
} else {
|
||||
this.arraySelectedContracts.push([contractId, status, bezeichnung]);
|
||||
}
|
||||
},*/
|
||||
toggleRowClick(event, vertrag_id, status, bezeichnung, vertragstyp_bezeichnung) {
|
||||
if (!this.dataPrintHonorar?.multiselect) return;
|
||||
|
||||
const isMulti = this.dataPrintHonorar?.multiselect === true;
|
||||
const isCtrl = event.ctrlKey || event.metaKey;
|
||||
|
||||
const entry = {
|
||||
@@ -540,28 +510,29 @@ export default {
|
||||
vertragstyp_bezeichnung
|
||||
};
|
||||
|
||||
// Single click
|
||||
if (!isCtrl) {
|
||||
// allow MultiSelect just in case event multiActionPrintHonorarvertrag
|
||||
const allowMultiClick = isMulti && isCtrl;
|
||||
|
||||
if (!allowMultiClick) {
|
||||
this.arraySelectedContracts = [entry];
|
||||
|
||||
//just mark last selected row as selected
|
||||
this.$refs.table.tabulator.deselectRow();
|
||||
this.$refs.table.tabulator.selectRow(vertrag_id);
|
||||
return;
|
||||
}
|
||||
|
||||
// CTRL / CMD → toggle
|
||||
const index = this.arraySelectedContracts.findIndex(
|
||||
e => e.vertrag_id === vertrag_id
|
||||
);
|
||||
|
||||
if (index === -1) {
|
||||
this.arraySelectedContracts.push(entry);
|
||||
//this.arraySelectedContracts.push([entry.vertrag_id, entry.status, entry.bezeichnung, entry.vertragstyp_bezeichnung]);
|
||||
} else {
|
||||
this.arraySelectedContracts.splice(index, 1);
|
||||
}
|
||||
},
|
||||
/* clearSelection(){
|
||||
this.arraySelectedContracts = [];
|
||||
this.$refs.table.tabulator.deselectRow();
|
||||
}*/
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
Promise.all([
|
||||
@@ -587,88 +558,6 @@ export default {
|
||||
});
|
||||
this.getFormattedDate();
|
||||
},
|
||||
/*
|
||||
TODO(Manu) delete after check
|
||||
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
type="DatePicker"
|
||||
:label="$p.t('vertrag/datum_vertrag')"
|
||||
name="vertragsdatum"
|
||||
v-model="formData.vertragsdatum"
|
||||
auto-apply
|
||||
:enable-time-picker="false"
|
||||
format="dd.MM.yyyy"
|
||||
preview-format="dd.MM.yyyy"
|
||||
:teleport="true"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
type="text"
|
||||
:label="$p.t('ui/bezeichnung')"
|
||||
name="bezeichnung"
|
||||
v-model="formData.bezeichnung"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
type="select"
|
||||
:label="$p.t('global/typ')"
|
||||
v-model="formData.vertragstyp_kurzbz"
|
||||
name="vertragstyp_kurzbz"
|
||||
>
|
||||
<option :value="null">-- {{$p.t('fehlermonitoring', 'keineAuswahl')}} --</option>
|
||||
<option
|
||||
v-for="entry in listContractTypes"
|
||||
:key="entry.vertragstyp_kurzbz"
|
||||
:value="entry.vertragstyp_kurzbz"
|
||||
>
|
||||
{{entry.bezeichnung}}
|
||||
</option>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
:label="$p.t('ui/betrag')"
|
||||
name="betrag"
|
||||
v-model="formData.betrag"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="row mb-3" v-if="!statusNew">
|
||||
<form-input
|
||||
type="text"
|
||||
:label="$p.t('ui/stunden') + ' (' + $p.t('vertrag/vertrag_urfassung')+ ')'"
|
||||
name="vertragsstunden"
|
||||
v-model="formData.vertragsstunden"
|
||||
disabled
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="row mb-3" v-if="!statusNew">
|
||||
<form-input
|
||||
type="text"
|
||||
:label="$p.t('lehre/studiensemester') + ' (' + $p.t('vertrag/vertrag_urfassung')+ ')'"
|
||||
name="vertragsstunden_studiensemester_kurzbz"
|
||||
v-model="formData.vertragsstunden_studiensemester_kurzbz"
|
||||
disabled
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
type="textarea"
|
||||
:label="$p.t('global/anmerkung')"
|
||||
name="anmerkung"
|
||||
v-model="formData.anmerkung"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
*/
|
||||
template: `
|
||||
<div class="core-contracts h-100 d-flex flex-column">
|
||||
|
||||
|
||||
@@ -71,7 +71,6 @@ export default {
|
||||
:mitarbeiter_uid="this.mitarbeiter_uid"
|
||||
typeHeader="mitarbeiter"
|
||||
:domain="config.domain"
|
||||
fotoEditable
|
||||
@redirectToLeitung="handleSelection"
|
||||
>
|
||||
<template #uid>{{tile_MaUid}}</template>
|
||||
|
||||
@@ -280,7 +280,7 @@ export const CoreFilterCmpt = {
|
||||
});
|
||||
}
|
||||
|
||||
if (tabulatorOptions.selectable || (tabulatorOptions.columns && tabulatorOptions.columns.filter(el => el.formatter == 'rowSelection').length))
|
||||
if (tabulatorOptions.selectable || tabulatorOptions.selectableRows || (tabulatorOptions.columns && tabulatorOptions.columns.filter(el => el.formatter == 'rowSelection').length))
|
||||
this.tabulatorHasSelector = true;
|
||||
|
||||
if (this.idField) {
|
||||
@@ -358,7 +358,7 @@ export const CoreFilterCmpt = {
|
||||
}
|
||||
},
|
||||
_updateTabulator() {
|
||||
this.tabulatorHasSelector = this.tabulatorOptions.selectable || this.filteredColumns.filter(el => el.formatter == 'rowSelection').length;
|
||||
this.tabulatorHasSelector = this.tabulatorOptions.selectable || this.tabulatorOptions.selectableRows || this.filteredColumns.filter(el => el.formatter == 'rowSelection').length;
|
||||
this.tabulator.setColumns(this.filteredColumns);
|
||||
this.tabulator.setData(this.filteredData);
|
||||
this._setHeaderFilter()
|
||||
|
||||
@@ -1,29 +1,36 @@
|
||||
let __widgets = {};
|
||||
let __widgetsStarted = {};
|
||||
let __path = FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/dashboard/Widget';
|
||||
import ApiWidget from "../../api/factory/dashboard/widget.js";
|
||||
|
||||
export default {
|
||||
getWidget(id) {
|
||||
return __widgets[id];
|
||||
},
|
||||
loadWidget(id) {
|
||||
if (__widgets[id])
|
||||
return Promise.resolve(__widgets[id]);
|
||||
if (__widgetsStarted[id])
|
||||
return __widgetsStarted[id];
|
||||
if (!__path)
|
||||
return Promise.reject('Widget could not be loaded because there is no path yet!');
|
||||
const promises = Vue.ref([]);
|
||||
const stateRef = Vue.ref([]);
|
||||
const state = Vue.readonly(stateRef);
|
||||
|
||||
__widgetsStarted[id] = new Promise((resolve, reject) => {
|
||||
axios.get(__path, {params:{id}}).then(res => {
|
||||
__widgets[id] = res.data.retval;
|
||||
__widgetsStarted[id] = undefined;
|
||||
resolve(__widgets[id]);
|
||||
}).catch(error => reject(error.response.data.retval.error));
|
||||
});
|
||||
return __widgetsStarted[id];
|
||||
},
|
||||
setPath(path) {
|
||||
__path = path;
|
||||
export function useCachedWidgetLoader() {
|
||||
const $api = Vue.inject('$api');
|
||||
const $fhcAlert = Vue.inject('$fhcAlert');
|
||||
|
||||
function load(id) {
|
||||
if (state.value[id])
|
||||
return Promise.resolve(state.value[id]);
|
||||
|
||||
if (!promises.value[id])
|
||||
promises.value[id] = new Promise((resolve, reject) => {
|
||||
$api
|
||||
.call(ApiWidget.get(id))
|
||||
.then(res => {
|
||||
stateRef.value[id] = res.data;
|
||||
promises.value[id] = undefined;
|
||||
resolve(state.value[id]);
|
||||
})
|
||||
.catch($fhcAlert.handleSystemError);
|
||||
});
|
||||
|
||||
return promises.value[id];
|
||||
}
|
||||
|
||||
return {
|
||||
state,
|
||||
actions: {
|
||||
load
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,31 +1,72 @@
|
||||
export default {
|
||||
/**
|
||||
* Performs a deep merge of objects and returns new object. Does not modify
|
||||
* objects (immutable) and merges arrays via concatenation.
|
||||
*
|
||||
* @param {...object} objects - Objects to merge
|
||||
* @returns {object} New object with merged key/values
|
||||
*/
|
||||
mergeDeep(...objects) {
|
||||
const isObject = obj => obj && typeof obj === 'object';
|
||||
|
||||
return objects.reduce((prev, obj) => {
|
||||
Object.keys(obj).forEach(key => {
|
||||
const pVal = prev[key];
|
||||
const oVal = obj[key];
|
||||
|
||||
if (Array.isArray(pVal) && Array.isArray(oVal)) {
|
||||
prev[key] = pVal.concat(...oVal);
|
||||
}
|
||||
else if (isObject(pVal) && isObject(oVal)) {
|
||||
prev[key] = this.mergeDeep(pVal, oVal);
|
||||
}
|
||||
else {
|
||||
prev[key] = oVal;
|
||||
}
|
||||
});
|
||||
/**
|
||||
* Performs a deep merge of objects and returns new object. Does not modify
|
||||
* objects (immutable) and merges arrays via concatenation.
|
||||
*
|
||||
* @param {...object} objects - Objects to merge
|
||||
* @returns {object} New object with merged key/values
|
||||
*/
|
||||
function mergeDeep(...objects) {
|
||||
const isObject = obj => obj && typeof obj === 'object';
|
||||
|
||||
return objects.reduce((prev, obj) => {
|
||||
Object.keys(obj).forEach(key => {
|
||||
const pVal = prev[key];
|
||||
const oVal = obj[key];
|
||||
|
||||
return prev;
|
||||
}, {});
|
||||
}
|
||||
if (Array.isArray(pVal) && Array.isArray(oVal)) {
|
||||
prev[key] = pVal.concat(...oVal);
|
||||
}
|
||||
else if (isObject(pVal) && isObject(oVal)) {
|
||||
prev[key] = this.mergeDeep(pVal, oVal);
|
||||
}
|
||||
else {
|
||||
prev[key] = oVal;
|
||||
}
|
||||
});
|
||||
|
||||
return prev;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends VUEs toRaw() function to nested Proxies
|
||||
* @see https://www.reddit.com/r/javascript/comments/10gzynk/deep_cloning_objects_in_javascript_the_modern_way/
|
||||
*
|
||||
* @param object sourceObj - Object to transform
|
||||
* @returns object
|
||||
*/
|
||||
function deepToRaw(sourceObj) {
|
||||
const objectIterator = input => {
|
||||
if (Array.isArray(input))
|
||||
return input.map(objectIterator);
|
||||
if (Vue.isRef(input) || Vue.isReactive(input) || Vue.isProxy(input))
|
||||
return objectIterator(Vue.toRaw(input));
|
||||
if (input && typeof input === 'object') {
|
||||
/** use custom handling of 'Date' objects to avoid data loss if treating it like any other object.
|
||||
* reminder:
|
||||
* typeof (new Date()) ==> 'object'
|
||||
* Object.keys(new Date()) ==> []
|
||||
*/
|
||||
if (input instanceof Date)
|
||||
return input;
|
||||
|
||||
return Object.keys(input).reduce((acc, key) => {
|
||||
acc[key] = objectIterator(input[key]);
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
return input;
|
||||
};
|
||||
|
||||
return objectIterator(sourceObj);
|
||||
}
|
||||
|
||||
export {
|
||||
mergeDeep,
|
||||
deepToRaw
|
||||
}
|
||||
export default {
|
||||
mergeDeep,
|
||||
deepToRaw
|
||||
}
|
||||
@@ -430,16 +430,16 @@ export default {
|
||||
|
||||
fhcApiAxios.interceptors.response.use(
|
||||
response => {
|
||||
if (response.config?.errorHandling == 'off'
|
||||
|| response.config?.errorHandling === false
|
||||
|| response.config?.errorHandling == 'fail')
|
||||
const errorConfig = get_error_handler(response.config);
|
||||
|
||||
if (!errorConfig.success)
|
||||
return clean_return_value(response);
|
||||
|
||||
// NOTE(chris): loop through errors
|
||||
if (response.data.errors)
|
||||
response.data.errors = response.data.errors.filter(
|
||||
err => (response.config[err.type + 'ErrorHandler'] || app.config.globalProperties.$api._defaultErrorHandlers[err.type])(err, response.config)
|
||||
);
|
||||
const errors = popHandleableErrors(errorConfig, response.data.errors);
|
||||
|
||||
for (var type in errors) {
|
||||
errorConfig.handler[type](errors[type]);
|
||||
}
|
||||
|
||||
return clean_return_value(response);
|
||||
},
|
||||
|
||||
@@ -144,6 +144,7 @@ foreach($ps->result as $row)
|
||||
<ROLLE:stichtagsaktiv><![CDATA['.$stichtagsaktiv.']]></ROLLE:stichtagsaktiv>
|
||||
<ROLLE:aktiv><![CDATA['.$aktiv.']]></ROLLE:aktiv>
|
||||
<ROLLE:fgm><![CDATA['.$row->fgm.']]></ROLLE:fgm>
|
||||
<ROLLE:faktiv><![CDATA['.($row->faktiv?'Ja':'Nein').']]></ROLLE:faktiv>
|
||||
</RDF:Description>
|
||||
</RDF:li>
|
||||
';
|
||||
|
||||
+3
-3
@@ -450,18 +450,18 @@ td.MarkLine
|
||||
td.HeaderTesttool /*fuer die Button-Optik beim Testtool*/
|
||||
{
|
||||
color: #FFFFFF;
|
||||
background-color: #00639C;
|
||||
background-color: #71787D;
|
||||
white-space:nowrap;
|
||||
line-height: 25px;
|
||||
box-shadow: inset 0 0 2px #FFFFFF;
|
||||
padding: 10px;
|
||||
padding: 0 10px;
|
||||
width: 170px;
|
||||
}
|
||||
td.HeaderTesttoolSTG /*fuer die Button-Optik der Quereinstiegs-Studiengänge beim Testtool*/
|
||||
{
|
||||
color: white;
|
||||
border: 2px solid #73a9d6;
|
||||
padding: 10px;
|
||||
padding: 0 10px;
|
||||
max-width: 100px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
+5998
-107
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user