mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 12:19:28 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -208,7 +208,14 @@ $config['navigation_header'] = array(
|
|||||||
'expand' => true,
|
'expand' => true,
|
||||||
'sort' => 30,
|
'sort' => 30,
|
||||||
'requiredPermissions' => 'lehre/anrechnungszeitfenster:rw'
|
'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;
|
return $projektarbeit->projektarbeit_id;
|
||||||
};
|
};
|
||||||
$projektarbeiten_ids = array_map($mapFunc, $projektarbeiten->retval);
|
$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) {
|
forEach($projektarbeiten->retval as $pa) {
|
||||||
|
|
||||||
@@ -846,9 +847,10 @@ class Abgabe extends FHCAPI_Controller
|
|||||||
private function getProjektbetreuerEmailByProjektarbeitID($projektarbeit_id) {
|
private function getProjektbetreuerEmailByProjektarbeitID($projektarbeit_id) {
|
||||||
$this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel');
|
$this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel');
|
||||||
$result = $this->ProjektarbeitModel->getProjektbetreuerEmail($projektarbeit_id);
|
$result = $this->ProjektarbeitModel->getProjektbetreuerEmail($projektarbeit_id);
|
||||||
$email = $this->getDataOrTerminateWithError($result, 'general');
|
if(count($result->retval) > 0) {
|
||||||
|
$email = getData($result);
|
||||||
return $email[0]->uid ? $email[0]->uid.'@'.DOMAIN : $email[0]->private_email;
|
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');
|
$this->load->model('system/Vorlage_model', 'VorlageModel');
|
||||||
|
|
||||||
$result = $this->VorlageModel->load($xsl);
|
$result = $this->VorlageModel->load($xsl);
|
||||||
$this->addMeta("ress", $result);
|
|
||||||
$vorlage = current($this->getDataOrTerminateWithError($result));
|
$vorlage = current($this->getDataOrTerminateWithError($result));
|
||||||
if (!$vorlage)
|
if (!$vorlage)
|
||||||
show_404();
|
show_404();
|
||||||
@@ -221,7 +220,7 @@ class Documents extends FHCAPI_Controller
|
|||||||
'gedruckt' => true,
|
'gedruckt' => true,
|
||||||
'insertamum' => date('c'),
|
'insertamum' => date('c'),
|
||||||
'insertvon' => getAuthUID(),
|
'insertvon' => getAuthUID(),
|
||||||
'uid' => $this->input->post_get('uid') ?: '',
|
'uid' => $this->input->post_get('uid') ?: null,
|
||||||
'archiv' => true,
|
'archiv' => true,
|
||||||
'signiert' => !!$sign_user,
|
'signiert' => !!$sign_user,
|
||||||
'stud_selfservice' => $vorlage->stud_selfservice
|
'stud_selfservice' => $vorlage->stud_selfservice
|
||||||
@@ -251,6 +250,9 @@ class Documents extends FHCAPI_Controller
|
|||||||
'studiensemester_kurzbz' => $ss,
|
'studiensemester_kurzbz' => $ss,
|
||||||
'student_uid' => $akteData['uid']
|
'student_uid' => $akteData['uid']
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if (!hasData($result)) $this->terminateWithError($this->p->t("stv", "error_noLehrverbandAssigned"));
|
||||||
|
|
||||||
$res = current($this->getDataOrTerminateWithError($result));
|
$res = current($this->getDataOrTerminateWithError($result));
|
||||||
|
|
||||||
$studiengang_kz = $res->studiengang_kz;
|
$studiengang_kz = $res->studiengang_kz;
|
||||||
@@ -332,6 +334,7 @@ class Documents extends FHCAPI_Controller
|
|||||||
if ($prestudent_id) {
|
if ($prestudent_id) {
|
||||||
$this->load->model('crm/prestudent_model', 'PrestudentModel');
|
$this->load->model('crm/prestudent_model', 'PrestudentModel');
|
||||||
$this->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz', 'LEFT');
|
$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);
|
$result = $this->PrestudentModel->load($prestudent_id);
|
||||||
$prestudent = current($this->getDataOrTerminateWithError($result));
|
$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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,6 +24,7 @@ class NotizPerson extends Notiz_Controller
|
|||||||
//Load Models
|
//Load Models
|
||||||
$this->load->model('person/Benutzer_model', 'BenutzerModel');
|
$this->load->model('person/Benutzer_model', 'BenutzerModel');
|
||||||
$this->load->model('crm/Student_model', 'StudentModel');
|
$this->load->model('crm/Student_model', 'StudentModel');
|
||||||
|
$this->load->model('crm/Prestudent_model', 'PrestudentModel');
|
||||||
|
|
||||||
//Permission checks for allowed Oes
|
//Permission checks for allowed Oes
|
||||||
if ($this->router->method == 'addNewNotiz')
|
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);
|
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')
|
if ( $this->router->method == 'updateNotiz')
|
||||||
@@ -59,7 +60,7 @@ class NotizPerson extends Notiz_Controller
|
|||||||
$person_id = current($data)->person_id;
|
$person_id = current($data)->person_id;
|
||||||
|
|
||||||
$allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: [];
|
$allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: [];
|
||||||
$this->_checkIfBerechtigungForOneUidExists($person_id, $allowedStgs);
|
$this->_checkIfBerechtigungForOnePrestudentExists($person_id, $allowedStgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->router->method == 'deleteNotiz' )
|
if ($this->router->method == 'deleteNotiz' )
|
||||||
@@ -78,7 +79,7 @@ class NotizPerson extends Notiz_Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: [];
|
$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
|
//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->PrestudentModel->loadWhere(['person_id' => $person_id]);
|
||||||
$result = $this->BenutzerModel->loadWhere(['person_id' => $person_id]);
|
|
||||||
$data = $this->getDataOrTerminateWithError($result);
|
$data = $this->getDataOrTerminateWithError($result);
|
||||||
|
|
||||||
$checkarray = [];
|
$checkarray = [];
|
||||||
foreach ($data as $item)
|
foreach ($data as $item)
|
||||||
{
|
{
|
||||||
//check if isStudent
|
if(in_array($item->studiengang_kz, $allowedStgs))
|
||||||
$result = $this->StudentModel->isStudent($item->uid);
|
|
||||||
|
|
||||||
$isStudent = $this->getDataOrTerminateWithError($result);
|
|
||||||
if($isStudent)
|
|
||||||
{
|
{
|
||||||
$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->terminateWithError($this->p->t('ui', 'error_keineBerechtigungStg'), self::ERROR_TYPE_GENERAL);
|
||||||
{
|
|
||||||
$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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
// get all new or changed termine in interval
|
||||||
$result = $this->_ci->PaabgabeModel->findAbgabenNewOrUpdatedSince($interval, $relevantTypes);
|
$result = $this->_ci->PaabgabeModel->findAbgabenNewOrUpdatedSince($interval, $relevantTypes);
|
||||||
$retval = getData($result);
|
$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
|
// group changed/new abgaben for projektarbeiten
|
||||||
$projektarbeiten = [];
|
$projektarbeiten = [];
|
||||||
@@ -557,6 +561,8 @@ class AbgabetoolJob extends JOB_Controller
|
|||||||
$anredeFillString = $data->anrede == "Herr" ? "r" : "";
|
$anredeFillString = $data->anrede == "Herr" ? "r" : "";
|
||||||
$fullFormattedNameString = $data->first;
|
$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) {
|
forEach($tupelArr as $tupel) {
|
||||||
$projektarbeit_id = $tupel[0];
|
$projektarbeit_id = $tupel[0];
|
||||||
$betreuerRow = $tupel[1];
|
$betreuerRow = $tupel[1];
|
||||||
@@ -575,6 +581,8 @@ class AbgabetoolJob extends JOB_Controller
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$relevantCounter++;
|
||||||
|
|
||||||
// format the Student Name
|
// format the Student Name
|
||||||
$s = $relevantAbgaben[0];
|
$s = $relevantAbgaben[0];
|
||||||
$nameParts = [];
|
$nameParts = [];
|
||||||
@@ -633,6 +641,11 @@ class AbgabetoolJob extends JOB_Controller
|
|||||||
// done with building the change list, now send it
|
// done with building the change list, now send it
|
||||||
$betreuerRow = $tupelArr[0][1];
|
$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');
|
$path = $this->_ci->config->item('URL_MITARBEITER');
|
||||||
$url = CIS_ROOT.$path;
|
$url = CIS_ROOT.$path;
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ class PermissionLib
|
|||||||
const LOGINAS_PERSONIDS_BLACKLIST = 'permission_loginas_personids_blacklist';
|
const LOGINAS_PERSONIDS_BLACKLIST = 'permission_loginas_personids_blacklist';
|
||||||
|
|
||||||
private $_ci; // CI instance
|
private $_ci; // CI instance
|
||||||
|
private $access_rights; // current users access rights
|
||||||
private static $bb; // benutzerberechtigung
|
private static $bb; // benutzerberechtigung
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,6 +62,8 @@ class PermissionLib
|
|||||||
// Loads CI instance
|
// Loads CI instance
|
||||||
$this->_ci =& get_instance();
|
$this->_ci =& get_instance();
|
||||||
|
|
||||||
|
$this->access_rights = null;
|
||||||
|
|
||||||
$this->_ci->config->load('permission'); // Loads permission configuration
|
$this->_ci->config->load('permission'); // Loads permission configuration
|
||||||
|
|
||||||
// If it's NOT called from command line
|
// If it's NOT called from command line
|
||||||
@@ -69,8 +72,10 @@ class PermissionLib
|
|||||||
// API Caller rights initialization
|
// API Caller rights initialization
|
||||||
$authObj = $this->_ci->authlib->getAuthObj();
|
$authObj = $this->_ci->authlib->getAuthObj();
|
||||||
self::$bb = new benutzerberechtigung();
|
self::$bb = new benutzerberechtigung();
|
||||||
if ($authObj)
|
if ($authObj) {
|
||||||
self::$bb->getBerechtigungen($authObj->{AuthLib::AO_USERNAME});
|
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
|
// Private methods
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class DashboardLib
|
|||||||
|
|
||||||
public function getMergedConfig($dashboard_id, $uid)
|
public function getMergedConfig($dashboard_id, $uid)
|
||||||
{
|
{
|
||||||
$defaultconfig = $this->getDefaultConfig($dashboard_id, $uid);
|
$defaultconfig = $this->getDefaultConfig($dashboard_id);
|
||||||
$userconfig = $this->getUserConfig($dashboard_id, $uid);
|
$userconfig = $this->getUserConfig($dashboard_id, $uid);
|
||||||
|
|
||||||
$mergedconfig = array_replace_recursive($defaultconfig, $userconfig);
|
$mergedconfig = array_replace_recursive($defaultconfig, $userconfig);
|
||||||
@@ -57,14 +57,31 @@ class DashboardLib
|
|||||||
return $mergedconfig;
|
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();
|
$defaultconfig = array();
|
||||||
|
|
||||||
if (hasData($res_presets))
|
if (hasData($result))
|
||||||
{
|
{
|
||||||
$presets = getData($res_presets);
|
$presets = getData($result);
|
||||||
foreach ($presets as $presetobj)
|
foreach ($presets as $presetobj)
|
||||||
{
|
{
|
||||||
$preset = json_decode($presetobj->preset, true);
|
$preset = json_decode($presetobj->preset, true);
|
||||||
@@ -137,8 +154,10 @@ class DashboardLib
|
|||||||
$dashboard = $this->getDashboardByKurzbz($dashboard_kurzbz);
|
$dashboard = $this->getDashboardByKurzbz($dashboard_kurzbz);
|
||||||
|
|
||||||
$funktion_kurzbz = ($section === self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL) ? null : $section;
|
$funktion_kurzbz = ($section === self::SECTION_IF_FUNKTION_KURZBZ_IS_NULL) ? null : $section;
|
||||||
$result = $this->_ci->DashboardPresetModel
|
$result = $this->_ci->DashboardPresetModel->loadWhere([
|
||||||
->getPresetByDashboardAndFunktion($dashboard->dashboard_id, $funktion_kurzbz);
|
'dashboard_id' => $dashboard->dashboard_id,
|
||||||
|
'funktion_kurzbz' => $funktion_kurzbz
|
||||||
|
]);
|
||||||
|
|
||||||
if (hasData($result))
|
if (hasData($result))
|
||||||
{
|
{
|
||||||
@@ -195,11 +214,11 @@ class DashboardLib
|
|||||||
{
|
{
|
||||||
foreach ($addwigets as $widget)
|
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']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,57 +11,4 @@ class Dashboard_Preset_model extends DB_Model
|
|||||||
$this->dbTable = 'dashboard.tbl_dashboard_preset';
|
$this->dbTable = 'dashboard.tbl_dashboard_preset';
|
||||||
$this->pk = 'preset_id';
|
$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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-3
@@ -8,9 +8,15 @@ $this->load->view(
|
|||||||
'axios027' => true,
|
'axios027' => true,
|
||||||
'restclient' => true,
|
'restclient' => true,
|
||||||
'vue3' => 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' => [
|
'customCSSs' => [
|
||||||
'public/css/components/dashboard.css'
|
'public/css/components/dashboard.css',
|
||||||
|
'public/css/components/primevue.css',
|
||||||
],
|
],
|
||||||
'navigationcomponent' => true
|
'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">
|
<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</h1>
|
||||||
</div>
|
</div>
|
||||||
<core-dashboard dashboard="CIS" apiurl="<?= site_url('dashboard'); ?>"></core-dashboard>
|
<dashboard-admin></dashboard-admin>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
+8
-3
@@ -8,7 +8,12 @@ $this->load->view(
|
|||||||
'axios027' => true,
|
'axios027' => true,
|
||||||
'restclient' => true,
|
'restclient' => true,
|
||||||
'vue3' => 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' => [
|
'customCSSs' => [
|
||||||
'public/css/components/dashboard.css'
|
'public/css/components/dashboard.css'
|
||||||
],
|
],
|
||||||
@@ -23,9 +28,9 @@ $this->load->view(
|
|||||||
|
|
||||||
<div id="content">
|
<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">
|
<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>
|
</div>
|
||||||
<dashboard-admin dashboard="CIS" apiurl="<?= site_url('dashboard'); ?>"></dashboard-admin>
|
<core-dashboard dashboard="<?= $dashboard_kurzbz ?>"></core-dashboard>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -3550,9 +3550,11 @@ function StudentZeugnisDokumentArchivieren()
|
|||||||
case 'microcredentialzertifikat_1':
|
case 'microcredentialzertifikat_1':
|
||||||
case 'microcredentialzertifikat_2':
|
case 'microcredentialzertifikat_2':
|
||||||
case 'microcredentialzertifikat_3':
|
case 'microcredentialzertifikat_3':
|
||||||
|
case 'microcredentialzertifikat_4':
|
||||||
case 'microcredential_1':
|
case 'microcredential_1':
|
||||||
case 'microcredential_2':
|
case 'microcredential_2':
|
||||||
case 'microcredential_3':
|
case 'microcredential_3':
|
||||||
|
case 'microcredential_4':
|
||||||
xml = 'microcredential.xml.php';
|
xml = 'microcredential.xml.php';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -552,9 +552,40 @@ class lehreinheitmitarbeiter extends basis_db
|
|||||||
$beginn = new DateTime($beginn);
|
$beginn = new DateTime($beginn);
|
||||||
$ende = new DateTime($ende);
|
$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 = '
|
$qry = '
|
||||||
WITH semester_sws_tbl AS (
|
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
|
||||||
FROM lehre.tbl_lehreinheitmitarbeiter lema
|
FROM lehre.tbl_lehreinheitmitarbeiter lema
|
||||||
JOIN lehre.tbl_lehreinheit USING (lehreinheit_id)
|
JOIN lehre.tbl_lehreinheit USING (lehreinheit_id)
|
||||||
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
|
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
|
||||||
@@ -564,38 +595,103 @@ class lehreinheitmitarbeiter extends basis_db
|
|||||||
JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz
|
JOIN public.tbl_studiengang stg ON stg.studiengang_kz = sto.studiengang_kz
|
||||||
JOIN public.tbl_studiensemester ss USING (studiensemester_kurzbz)
|
JOIN public.tbl_studiensemester ss USING (studiensemester_kurzbz)
|
||||||
WHERE mitarbeiter_uid = '. $this->db_add_param($uid). '
|
WHERE mitarbeiter_uid = '. $this->db_add_param($uid). '
|
||||||
AND (
|
AND ss.studiensemester_kurzbz IN ('.$this->implode4SQL($studiensemester_kurzbz_arr).')
|
||||||
ss.start BETWEEN
|
|
||||||
'. $this->db_add_param($beginn->format('Y-m-d')). ' AND
|
|
||||||
'. $this->db_add_param($ende->format('Y-m-d')). ')
|
|
||||||
-- nur lehre, die bisgemeldet wird
|
-- nur lehre, die bisgemeldet wird
|
||||||
AND lema.bismelden
|
AND lema.bismelden
|
||||||
-- keine lehreinheiten ohne semesterstunden
|
-- keine lehreinheiten ohne semesterstunden
|
||||||
AND lema.semesterstunden != 0
|
AND lema.semesterstunden != 0
|
||||||
)
|
)
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
studiengang_kz,
|
studiengang_kz,
|
||||||
studiensemester_kurzbz,
|
studiensemester_kurzbz,
|
||||||
|
melde_studiengang_kz,
|
||||||
|
lgartcode,
|
||||||
sum(semesterstunden) AS summe,
|
sum(semesterstunden) AS summe,
|
||||||
round(sum(semesterstunden) / 15, 2) AS sws
|
round(sum(semesterstunden) / 15, 2) AS sws
|
||||||
FROM
|
FROM
|
||||||
semester_sws_tbl
|
semester_sws_tbl
|
||||||
GROUP BY
|
GROUP BY
|
||||||
studiengang_kz,
|
studiengang_kz,
|
||||||
studiensemester_kurzbz
|
studiensemester_kurzbz,
|
||||||
|
melde_studiengang_kz,
|
||||||
|
lgartcode
|
||||||
ORDER BY
|
ORDER BY
|
||||||
studiengang_kz;
|
studiengang_kz;
|
||||||
';
|
';
|
||||||
|
|
||||||
if ($this->db_query($qry))
|
if ($this->db_query($qry))
|
||||||
{
|
{
|
||||||
|
$additionalLehrgaenge = [];
|
||||||
|
|
||||||
while($row = $this->db_fetch_object())
|
while($row = $this->db_fetch_object())
|
||||||
{
|
{
|
||||||
$obj = new StdClass();
|
$obj = new StdClass();
|
||||||
$obj->studiengang_kz = $row->studiengang_kz;
|
$obj->studiengang_kz = $row->studiengang_kz;
|
||||||
$obj->studiensemester_kurzbz = $row->studiensemester_kurzbz;
|
$obj->studiensemester_kurzbz = $row->studiensemester_kurzbz;
|
||||||
|
$obj->melde_studiengang_kz = $row->melde_studiengang_kz;
|
||||||
|
$obj->lgartcode = $row->lgartcode;
|
||||||
$obj->sws = $row->sws;
|
$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;
|
$this->result []= $obj;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -655,4 +751,63 @@ class lehreinheitmitarbeiter extends basis_db
|
|||||||
return false;
|
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 == '')) {
|
} 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
|
// if bis datum is not yet known but von is available already
|
||||||
$zusatz .= '(o)(ab '.$datum->formatDatum($row->von, 'd.m.Y').')';
|
$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').')';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -193,3 +193,6 @@
|
|||||||
word-break: break-word;
|
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
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -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 DashboardAdmin from '../../components/Dashboard/Admin.js';
|
||||||
|
|
||||||
import PluginsPhrasen from '../../plugins/Phrasen.js';
|
import PluginsPhrasen from '../../plugins/Phrasen.js';
|
||||||
|
|
||||||
|
import ApiRenderers from '../../api/factory/renderers.js';
|
||||||
|
|
||||||
const app = Vue.createApp({
|
const app = Vue.createApp({
|
||||||
name: 'AdminApp',
|
name: 'DashboardAdminApp',
|
||||||
data: () => ({
|
data: () => ({
|
||||||
appSideMenuEntries: {}
|
appSideMenuEntries: {},
|
||||||
}),
|
renderers: null
|
||||||
components: {
|
}),
|
||||||
CoreNavigationCmpt,
|
components: {
|
||||||
DashboardAdmin
|
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.use(PluginsPhrasen);
|
||||||
|
app.directive('tooltip', primevue.tooltip);
|
||||||
app.mount('#main');
|
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');
|
||||||
@@ -17,7 +17,7 @@ export default {
|
|||||||
</template>
|
</template>
|
||||||
<template v-slot:footer>
|
<template v-slot:footer>
|
||||||
<button type="button" class="btn btn-primary" @click="result=true;this.hide()">OK</button>
|
<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>
|
</template>
|
||||||
</bs-modal>`
|
</bs-modal>`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ export const AbgabetoolAssistenz = {
|
|||||||
// frozen: true,
|
// frozen: true,
|
||||||
// width: 40
|
// 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/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/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},
|
{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},
|
field: 'qgate2Status', formatter: this.centeredTextFormatter, widthGrow: 1, width: 220, tooltip: false},
|
||||||
],
|
],
|
||||||
persistence: false,
|
persistence: false,
|
||||||
persistenceID: "abgabetool_2026_02_26"
|
persistenceID: "abgabetool_2026_03_16"
|
||||||
},
|
},
|
||||||
abgabeTableEventHandlers: [
|
abgabeTableEventHandlers: [
|
||||||
{
|
{
|
||||||
@@ -645,7 +645,7 @@ export const AbgabetoolAssistenz = {
|
|||||||
actionButtons.className = "d-flex gap-3"; // you can keep Bootstrap gap if loaded
|
actionButtons.className = "d-flex gap-3"; // you can keep Bootstrap gap if loaded
|
||||||
actionButtons.style.display = "flex";
|
actionButtons.style.display = "flex";
|
||||||
actionButtons.style.alignItems = "stretch"; // buttons stretch to full height
|
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
|
actionButtons.style.height = "100%"; // full grid cell height
|
||||||
|
|
||||||
const val = cell.getValue();
|
const val = cell.getValue();
|
||||||
@@ -675,8 +675,20 @@ export const AbgabetoolAssistenz = {
|
|||||||
createButton('fa fa-timeline', 'abgabetool/c4termineTimeLine', () => this.openTimeline(val))
|
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;
|
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) {
|
undoSelection(cell) {
|
||||||
// checks if cells row is selected and unselects -> imitates columns which dont trigger row selection
|
// 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
|
// TODO: mehrsprachig englisch
|
||||||
projekt.note_bez = opt.bezeichnung
|
projekt.note_bez = opt.bezeichnung
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const latestTerminWithUpload = this.findLatestTerminWithUpload(projekt)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...projekt,
|
...projekt,
|
||||||
@@ -787,6 +801,7 @@ export const AbgabetoolAssistenz = {
|
|||||||
details: {
|
details: {
|
||||||
student_uid: projekt.student_uid,
|
student_uid: projekt.student_uid,
|
||||||
projektarbeit_id: projekt.projektarbeit_id,
|
projektarbeit_id: projekt.projektarbeit_id,
|
||||||
|
latestTerminWithUpload: latestTerminWithUpload ?? null
|
||||||
},
|
},
|
||||||
pkz: this.buildPKZ(projekt),
|
pkz: this.buildPKZ(projekt),
|
||||||
beurteilung: projekt.beurteilungLink ?? null,
|
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) {
|
createInfoString(data) {
|
||||||
let str = '';
|
let str = '';
|
||||||
|
|
||||||
@@ -1413,9 +1437,12 @@ export const AbgabetoolAssistenz = {
|
|||||||
|
|
||||||
<div id="abgabetable" style="max-height:40vw;">
|
<div id="abgabetable" style="max-height:40vw;">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-auto">
|
<div class="col-auto me-auto">
|
||||||
<h2 tabindex="1">{{$p.t('abgabetool/abgabetoolTitle')}}</h2>
|
<h2 tabindex="1">{{$p.t('abgabetool/abgabetoolTitle')}}</h2>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<label class="col-form-label">{{$capitalize($p.t('lehre/studiengang'))}}:</label>
|
||||||
|
</div>
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
:placeholder="$capitalize($p.t('lehre/studiengang'))"
|
:placeholder="$capitalize($p.t('lehre/studiengang'))"
|
||||||
@@ -1430,6 +1457,9 @@ export const AbgabetoolAssistenz = {
|
|||||||
</template>
|
</template>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<label class="col-form-label">{{$capitalize($p.t('lehre/note'))}}:</label>
|
||||||
|
</div>
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<Dropdown
|
<Dropdown
|
||||||
:placeholder="$p.t('lehre/note')"
|
:placeholder="$p.t('lehre/note')"
|
||||||
|
|||||||
@@ -667,8 +667,10 @@ export const AbgabetoolMitarbeiter = {
|
|||||||
setDetailComponent(details){
|
setDetailComponent(details){
|
||||||
this.loading=true
|
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
|
let paIsBenotet = false
|
||||||
if(pa.note !== undefined && pa.note !== null) {
|
if(pa.note !== undefined && pa.note !== null) {
|
||||||
// check if the note is not defined as a non final projektarbeit note
|
// 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 DashboardAdminWidgets from "./Admin/Widgets.js";
|
||||||
import DashboardAdminPresets from "./Admin/Presets.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 {
|
export default {
|
||||||
|
name: 'DashboardAdmin',
|
||||||
components: {
|
components: {
|
||||||
DashboardAdminEdit,
|
DashboardAdminEdit,
|
||||||
DashboardAdminWidgets,
|
DashboardAdminWidgets,
|
||||||
DashboardAdminPresets
|
DashboardAdminPresets,
|
||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
adminMode: true
|
adminMode: true,
|
||||||
|
widgetsSetup: Vue.computed(() => this.dashboards[this.current] ? this.dashboards[this.current].widgetSetup : null)
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@@ -22,9 +27,6 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
apiurl() {
|
|
||||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/dashboard';
|
|
||||||
},
|
|
||||||
dashboard() {
|
dashboard() {
|
||||||
return this.dashboards.find(el => el.dashboard_id == this.current);
|
return this.dashboards.find(el => el.dashboard_id == this.current);
|
||||||
}
|
}
|
||||||
@@ -35,33 +37,50 @@ export default {
|
|||||||
BsPrompt.popup('New Dashboard name').then(
|
BsPrompt.popup('New Dashboard name').then(
|
||||||
name => {
|
name => {
|
||||||
_name = name;
|
_name = name;
|
||||||
return axios.post(this.apiurl + '/Dashboard/create', {
|
const params = {
|
||||||
dashboard_kurzbz: name
|
dashboard_kurzbz: name
|
||||||
})
|
};
|
||||||
}
|
return this.$api
|
||||||
).then(res => {
|
.call(ApiDashboardBoard.add(params))
|
||||||
let newDashboard = {
|
.then(response =>{
|
||||||
dashboard_id: res.data.retval,
|
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
|
||||||
dashboard_kurzbz: _name,
|
|
||||||
beschreibung: ''
|
let newDashboard = {
|
||||||
};
|
dashboard_id: response.data,
|
||||||
this.dashboards.push(newDashboard);
|
dashboard_kurzbz: _name,
|
||||||
this.current = newDashboard.dashboard_id;
|
beschreibung: ''
|
||||||
}).catch(err => err !== undefined ? console.error('ERROR:', err) : 0);
|
};
|
||||||
|
this.dashboards.push(newDashboard);
|
||||||
|
this.current = newDashboard.dashboard_id;
|
||||||
|
})
|
||||||
|
.catch(this.$fhcAlert.handleSystemError);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
dashboardUpdate(dashboard) {
|
dashboardUpdate(dashboard) {
|
||||||
// TODO(chris): Loading or message
|
return this.$api
|
||||||
axios.post(this.apiurl + '/Dashboard/update', dashboard).then(() => {
|
.call(ApiDashboardBoard.update(dashboard))
|
||||||
let old = this.dashboards.find(el => el.dashboard_id == dashboard.dashboard_id);
|
.then(response =>{
|
||||||
old.dashboard_kurzbz = dashboard.dashboard_kurzbz;
|
|
||||||
old.beschreibung = dashboard.beschreibung;
|
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
|
||||||
}).catch(err => console.error('ERROR:', err));
|
|
||||||
|
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) {
|
dashboardDelete(dashboard_id) {
|
||||||
axios.post(this.apiurl + '/Dashboard/delete', {dashboard_id}).then(() => {
|
return this.$api
|
||||||
this.current = -1;
|
.call(ApiDashboardBoard.delete(dashboard_id))
|
||||||
this.dashboards = this.dashboards.filter(el => el.dashboard_id != dashboard_id);
|
.then(response => {
|
||||||
}).catch(err => console.error('ERROR:', err));
|
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) {
|
assignWidgets(widgets) {
|
||||||
this.widgets = widgets;
|
this.widgets = widgets;
|
||||||
@@ -72,22 +91,35 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
axios.get(this.apiurl + '/Dashboard').then(res => {
|
this.$api
|
||||||
this.dashboards = res.data.retval;
|
.call(ApiDashboardBoard.list())
|
||||||
}).catch(err => console.error('ERROR:', err));
|
.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">
|
template: `<div class="dashboard-admin">
|
||||||
|
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<label for="dashbaord-select" class="input-group-text">Dashboard:</label>
|
<label for="dashboard-select" class="input-group-text">Dashboard:</label>
|
||||||
<select id="dashbaord-select" class="form-select" v-model="current">
|
<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>
|
<option v-for="dashboard in dashboards" :key="dashboard.dashboard_id" :value="dashboard.dashboard_id">{{dashboard.dashboard_kurzbz}}</option>
|
||||||
</select>
|
</select>
|
||||||
<button class="btn btn-outline-secondary" type="button" @click="dashboardAdd"><i class="fa-solid fa-plus"></i></button>
|
<button class="btn btn-outline-secondary" type="button" @click="dashboardAdd"><i class="fa-solid fa-plus"></i></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="dashboard">
|
<div v-if="dashboard">
|
||||||
<ul class="nav nav-tabs mt-3" role="tablist">
|
<ul class="nav nav-tabs mt-3" role="tablist">
|
||||||
<li class="nav-item" role="presentation">
|
<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>
|
||||||
<li class="nav-item" role="presentation">
|
<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>
|
<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>
|
<dashboard-admin-edit v-bind="dashboard" :key="dashboard.dashboard_id" @change="dashboardUpdate($event)" @delete="dashboardDelete($event)"></dashboard-admin-edit>
|
||||||
</div>
|
</div>
|
||||||
<div class="tab-pane fade show active" id="widgets" role="tabpanel" aria-labelledby="widgets-tab">
|
<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>
|
||||||
<div class="tab-pane fade" id="presets" role="tabpanel" aria-labelledby="presets-tab">
|
<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>
|
<dashboard-admin-presets :dashboard="dashboard.dashboard_kurzbz" :widgets="widgets"></dashboard-admin-presets>
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
sendDelete() {
|
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">
|
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>
|
<textarea id="dashboard-admin-edit-beschreibung" class="form-control" v-model="desc"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button class="btn btn-danger" @click="sendDelete">Delete</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})">Update</button>
|
<button class="btn btn-primary" @click="$emit('change', {dashboard_id,dashboard_kurzbz:kurzbz,beschreibung:desc})">{{this.$p.t('ui', 'btnAktualisieren')}}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>`
|
</div>`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import DashboardSection from "../Section.js";
|
import DashboardSection from "../Section.js";
|
||||||
import DashboardWidgetPicker from "../Widget/Picker.js";
|
import DashboardWidgetPicker from "../Widget/Picker.js";
|
||||||
import ObjectUtils from "../../../helpers/ObjectUtils.js";
|
import ObjectUtils from "../../../helpers/ObjectUtils.js";
|
||||||
|
import ApiDashboardPreset from "../../../api/factory/dashboard/preset.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -17,9 +18,6 @@ export default {
|
|||||||
tmpLoading: ''
|
tmpLoading: ''
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
apiurl() {
|
|
||||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/dashboard';
|
|
||||||
},
|
|
||||||
pickerWidgets() {
|
pickerWidgets() {
|
||||||
return this.widgets.filter(widget => widget.allowed);
|
return this.widgets.filter(widget => widget.allowed);
|
||||||
}
|
}
|
||||||
@@ -28,6 +26,7 @@ export default {
|
|||||||
widgetAdd(section_name, widget) {
|
widgetAdd(section_name, widget) {
|
||||||
this.$refs.widgetpicker.getWidget().then(widget_id => {
|
this.$refs.widgetpicker.getWidget().then(widget_id => {
|
||||||
widget.widget = widget_id;
|
widget.widget = widget_id;
|
||||||
|
widget.id = 'loading_' + String((new Date()).valueOf());
|
||||||
delete widget.custom;
|
delete widget.custom;
|
||||||
widget.preset = 1;
|
widget.preset = 1;
|
||||||
let loading = {...widget};
|
let loading = {...widget};
|
||||||
@@ -36,130 +35,153 @@ export default {
|
|||||||
if (section.name == section_name)
|
if (section.name == section_name)
|
||||||
section.widgets.push(loading);
|
section.widgets.push(loading);
|
||||||
});
|
});
|
||||||
|
|
||||||
axios.post(this.apiurl + '/Config/addWidgetsToPreset', {
|
const params = {
|
||||||
db: this.dashboard,
|
dashboard: this.dashboard,
|
||||||
funktion_kurzbz: section_name,
|
funktion_kurzbz: section_name,
|
||||||
widgets: [widget]
|
widget
|
||||||
}).then(result => {
|
};
|
||||||
let newId = Object.keys(result.data.retval.data[section_name].widgets).pop();
|
|
||||||
widget.id = newId;
|
return this.$api
|
||||||
widget.custom = 1;
|
.call(ApiDashboardPreset.addWidget(params))
|
||||||
this.sections.forEach(section => {
|
.then(result => {
|
||||||
if (section.name == section_name) {
|
let newId = result.data;
|
||||||
section.widgets.splice(section.widgets.indexOf(loading),1);
|
widget.id = newId;
|
||||||
section.widgets.push(widget);
|
widget.custom = 1;
|
||||||
}
|
this.sections.forEach(section => {
|
||||||
});
|
if (section.name == section_name) {
|
||||||
}).catch(error => {
|
section.widgets.splice(section.widgets.indexOf(loading),1);
|
||||||
console.error('ERROR: ', error);
|
section.widgets.push(widget);
|
||||||
alert('ERROR: ' + error.response.data.retval);
|
}
|
||||||
});
|
});
|
||||||
}).catch(() => {});
|
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) {
|
widgetUpdate(section_name, payload) {
|
||||||
payload = payload[section_name];
|
payload = payload[section_name];
|
||||||
for (var k in payload) {
|
for (var k in payload) {
|
||||||
for (var i in this.sections) {
|
const section = this.sections.find(section => section.name == section_name);
|
||||||
if (this.sections[i].name == section_name) {
|
for (var wid in section.widgets) {
|
||||||
for (var wid in this.sections[i].widgets) {
|
if (section.widgets[wid].id == k) {
|
||||||
if (this.sections[i].widgets[wid].id == k) {
|
payload[k] = ObjectUtils.mergeDeep(section.widgets[wid], payload[k]);
|
||||||
payload[k] = ObjectUtils.mergeDeep(this.sections[i].widgets[wid], payload[k]);
|
// NOTE(chris): remove internal props
|
||||||
// NOTE(chris): remove internal props
|
for (var prop of ['_x', '_y', '_w', '_h', 'index', 'id'])
|
||||||
for (var prop in {_x:1,_y:1,_w:1,_h:1,index:1,id:1})
|
if (payload[k][prop])
|
||||||
if (payload[k][prop])
|
delete payload[k][prop];
|
||||||
delete payload[k][prop];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
payload[k].widgetid = k;
|
payload[k].widgetid = k;
|
||||||
delete payload[k].custom;
|
delete payload[k].custom;
|
||||||
}
|
}
|
||||||
axios.post(this.apiurl + '/Config/addWidgetsToPreset', {
|
this.$api
|
||||||
db: this.dashboard,
|
.call(Object.entries(payload).map(([key, widget]) => [
|
||||||
funktion_kurzbz: section_name,
|
key,
|
||||||
widgets: payload
|
ApiDashboardPreset.addWidget({
|
||||||
}).then(() => {
|
dashboard: this.dashboard,
|
||||||
this.sections.forEach(section => {
|
funktion_kurzbz: section_name,
|
||||||
if (section.name == section_name) {
|
widget
|
||||||
section.widgets.forEach((widget, i) => {
|
})
|
||||||
if (payload[widget.id]) {
|
]))
|
||||||
payload[widget.id].id = widget.id;
|
.then(result => {
|
||||||
payload[widget.id].index = widget.index;
|
this.sections.forEach(section => {
|
||||||
section.widgets[i] = payload[widget.id];
|
if (section.name == section_name) {
|
||||||
section.widgets[i].custom = 1;
|
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];
|
||||||
}).catch(error => {
|
section.widgets[i].custom = 1;
|
||||||
// TODO(chris): revert placement on failure
|
}
|
||||||
console.error('ERROR: ', error);
|
});
|
||||||
alert('ERROR: ' + error.response.data.retval);
|
}
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.catch(this.$fhcAlert.handleSystemError);
|
||||||
},
|
},
|
||||||
widgetRemove(section_name, id) {
|
widgetRemove(section_name, id) {
|
||||||
axios.post(this.apiurl + '/Config/removeWidgetFromPreset', {
|
const params = {
|
||||||
db: this.dashboard,
|
db: this.dashboard,
|
||||||
funktion_kurzbz: section_name,
|
funktion_kurzbz: section_name,
|
||||||
widgetid: id
|
widgetid: id
|
||||||
}).then(() => {
|
};
|
||||||
this.sections.forEach(section => {
|
return this.$api
|
||||||
if (section.name == section_name)
|
.call(ApiDashboardPreset.removeWidget(params))
|
||||||
section.widgets = section.widgets.filter(widget => widget.id != id);
|
.then(result => {
|
||||||
});
|
this.sections.forEach(section => {
|
||||||
}).catch(error => {
|
if (section.name == section_name)
|
||||||
console.error('ERROR: ', error);
|
section.widgets = section.widgets.filter(widget => widget.id != id);
|
||||||
alert('ERROR: ' + error.response.data.retval);
|
});
|
||||||
});
|
})
|
||||||
|
.catch(this.$fhcAlert.handleSystemError);
|
||||||
},
|
},
|
||||||
loadSections(evt) {
|
loadSections(evt) {
|
||||||
let funktionen = Array.from(evt.target.querySelectorAll("option:checked"),e=>e.value);
|
let funktionen = Array.from(evt.target.querySelectorAll("option:checked"),e=>e.value);
|
||||||
this.sections = [];
|
this.sections = [];
|
||||||
this.tmpLoading = funktionen.join('###');
|
this.tmpLoading = funktionen.join('###');
|
||||||
axios.get(this.apiurl + '/Config/presetBatch', {params: {
|
|
||||||
|
const params = {
|
||||||
db: this.dashboard,
|
db: this.dashboard,
|
||||||
funktionen
|
funktionen
|
||||||
}}).then(res => {
|
};
|
||||||
if (this.tmpLoading !== funktionen.join('###'))
|
|
||||||
return; // NOTE(chris): prevent race condition
|
return this.$api
|
||||||
for (var section in res.data.retval) {
|
.call(ApiDashboardPreset.getBatch(params))
|
||||||
let widgets = [];
|
.then(result => {
|
||||||
for (var wid in res.data.retval[section]) {
|
if (this.tmpLoading !== funktionen.join('###'))
|
||||||
res.data.retval[section][wid].id = wid;
|
return; // NOTE(chris): prevent race condition
|
||||||
res.data.retval[section][wid].custom = 1;
|
for (var section in result.data) {
|
||||||
widgets.push(res.data.retval[section][wid]);
|
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,
|
.catch(this.$fhcAlert.handleSystemError);
|
||||||
widgets
|
|
||||||
});
|
},
|
||||||
}
|
loadFunktionen() {
|
||||||
}).catch(err => console.error('ERROR:', err));
|
this.$api
|
||||||
|
.call(ApiDashboardPreset.list(this.dashboard))
|
||||||
|
.then(result => {
|
||||||
|
this.funktionen = result.data;
|
||||||
|
})
|
||||||
|
.catch(this.$fhcAlert.handleSystemError);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
axios.get(this.apiurl + '/Config/funktionen').then(res => {
|
this.loadFunktionen();
|
||||||
this.funktionen = {general: 'GENERAL'};
|
|
||||||
res.data.retval.forEach(funktion => {
|
|
||||||
this.funktionen[funktion.funktion_kurzbz] = funktion.beschreibung;
|
|
||||||
});
|
|
||||||
}).catch(err => console.error('ERROR:', err));
|
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
dashboard() {
|
dashboard() {
|
||||||
// TODO(chris): this should be done without a watcher
|
// TODO(chris): this should be done without a watcher
|
||||||
this.loadSections({target:this.$refs.funktionenList});
|
this.loadSections({target:this.$refs.funktionenList});
|
||||||
|
this.loadFunktionen();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
template: `<div class="dashboard-admin-presets">
|
template: `<div class="dashboard-admin-presets">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<select ref="funktionenList" style="height:30em" class="form-control" multiple @input="loadSections">
|
<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>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-9">
|
<div class="col-9">
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import ApiDashboardWidget from "../../../api/factory/dashboard/widget.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
emits: [
|
emits: [
|
||||||
"change",
|
"change",
|
||||||
@@ -7,34 +9,25 @@ export default {
|
|||||||
dashboard_id: Number,
|
dashboard_id: Number,
|
||||||
widgets: Array
|
widgets: Array
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
apiurl() {
|
|
||||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/dashboard';
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
sendChange(widget_id) {
|
sendChange(widget_id) {
|
||||||
let allow = !this.widgets.find(el => el.widget_id == widget_id).allowed;
|
let allow = !this.widgets.find(el => el.widget_id == widget_id).allowed;
|
||||||
axios.post(this.apiurl + '/Widget/setAllowed', {
|
|
||||||
dashboard_id: this.dashboard_id,
|
this.$api
|
||||||
widget_id,
|
.call(ApiDashboardWidget.setAllowed(this.dashboard_id, widget_id, allow))
|
||||||
action: allow ? 'add' : 'delete'
|
.catch(this.$fhcAlert.handleSystemError);
|
||||||
}).catch(err => console.error('ERROR: ' + err));
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
axios.get(this.apiurl + '/Widget/getAll', {
|
this.$api
|
||||||
params:{
|
.call(ApiDashboardWidget.list(this.dashboard_id))
|
||||||
dashboard_id: this.dashboard_id
|
.then(result => {
|
||||||
}
|
this.$emit('assignWidgets', result.data.map(el => ({
|
||||||
}).then(
|
|
||||||
result => {
|
|
||||||
this.$emit('assignWidgets', result.data.retval.map(el => ({
|
|
||||||
...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: `
|
template: `
|
||||||
<div class="dashboard-admin-widgets">
|
<div class="dashboard-admin-widgets">
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import DashboardSection from "./Section.js";
|
|||||||
import DashboardWidgetPicker from "./Widget/Picker.js";
|
import DashboardWidgetPicker from "./Widget/Picker.js";
|
||||||
import ObjectUtils from "../../helpers/ObjectUtils.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 {
|
export default {
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
@@ -20,181 +21,147 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
validator(value) {
|
validator(value) {
|
||||||
return value && value.name && value.uid && value.timezone
|
return value && value.name && value.timezone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
sections: [],
|
widgets: [],
|
||||||
widgets: null,
|
originalWidgets: {},
|
||||||
editMode: false,
|
widgetsSetup: null,
|
||||||
viewDataInternal: this.viewData
|
editMode: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
return {
|
return {
|
||||||
editMode: Vue.computed(()=>this.editMode),
|
editMode: Vue.computed(()=>this.editMode),
|
||||||
widgetsSetup: Vue.computed(() => this.widgets),
|
widgetsSetup: Vue.computed(() => this.widgetsSetup),
|
||||||
timezone: Vue.computed(() => this.viewData.timezone)
|
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: {
|
methods: {
|
||||||
widgetAdd(section_name, widget) {
|
widgetAdd(section_name, widget) {
|
||||||
if (this.widgets === null) {
|
// TODO(chris): remove section_name? (change order of params => get rid of it)
|
||||||
axios.get(this.apiurl + '/Widget/getWidgetsForDashboard', {params:{
|
this.$refs.widgetpicker
|
||||||
db: this.dashboard
|
.getWidget()
|
||||||
}}).then(res => {
|
.then(widget_id => {
|
||||||
res.data.retval.forEach(widget => {
|
widget.widget = widget_id;
|
||||||
widget.arguments = JSON.parse(widget.arguments);
|
widget.id = 'loading_' + String((new Date()).valueOf());
|
||||||
widget.setup = JSON.parse(widget.setup);
|
let loading = { ...widget };
|
||||||
});
|
loading.loading = true;
|
||||||
this.widgets = res.data.retval;
|
this.widgets.push(loading);
|
||||||
}).catch(err => console.error('ERROR:', err));
|
|
||||||
}
|
this.$api
|
||||||
this.$refs.widgetpicker.getWidget().then(widget_id => {
|
.call(ApiDashboardUser.addWidget(this.dashboard, widget))
|
||||||
widget.widget = widget_id;
|
.then(result => {
|
||||||
widget.id = 'loading_' + String((new Date()).valueOf());
|
widget.id = result.data;
|
||||||
let loading = {...widget};
|
this.widgets.splice(this.widgets.indexOf(loading), 1);
|
||||||
loading.loading = true;
|
this.widgets.push(widget);
|
||||||
this.sections.forEach(section => {
|
this.originalWidgets[widget.id] = structuredClone(ObjectUtils.deepToRaw(widget));
|
||||||
if (section.name == section_name)
|
})
|
||||||
section.widgets.push(loading);
|
.catch(this.$fhcAlert.handleSystemError);
|
||||||
});
|
})
|
||||||
|
.catch(() => {});
|
||||||
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(() => {});
|
|
||||||
},
|
},
|
||||||
widgetUpdate(section_name, payload) {
|
widgetUpdate(section_name, payload) {
|
||||||
payload = payload[section_name];
|
payload = payload[section_name];
|
||||||
for (var k in payload) {
|
for (var k in payload) {
|
||||||
for (var i in this.sections) {
|
for (var wid in this.widgets) {
|
||||||
if (this.sections[i].name == section_name) {
|
if (this.widgets[wid].id == k) {
|
||||||
for (var wid in this.sections[i].widgets) {
|
payload[k] = ObjectUtils.mergeDeep(this.widgets[wid], payload[k]);
|
||||||
if (this.sections[i].widgets[wid].id == k) {
|
// NOTE(chris): remove internal props
|
||||||
payload[k] = ObjectUtils.mergeDeep(this.sections[i].widgets[wid], payload[k]);
|
for (var prop of ['_x','_y','_w','_h','index','id','preset'])
|
||||||
// NOTE(chris): remove internal props
|
if (payload[k][prop])
|
||||||
for (var prop in {_x:1,_y:1,_w:1,_h:1,index:1,id:1,preset:1})
|
delete payload[k][prop];
|
||||||
if (payload[k][prop])
|
|
||||||
delete payload[k][prop];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
payload[k].widgetid = k;
|
payload[k].widgetid = k;
|
||||||
}
|
}
|
||||||
axios.post(this.apiurl + '/Config/addWidgetsToUserOverride', {
|
this.$api
|
||||||
db: this.dashboard,
|
.call(Object.entries(payload).map(([key, widget]) => [
|
||||||
funktion_kurzbz: section_name,
|
key,
|
||||||
widgets: payload
|
ApiDashboardUser.addWidget(this.dashboard, widget)
|
||||||
}).then(() => {
|
]))
|
||||||
this.sections.forEach(section => {
|
.then(result => {
|
||||||
if (section.name == section_name) {
|
const failed = result
|
||||||
section.widgets.forEach((widget, i) => {
|
.filter(o => o.status == 'rejected')
|
||||||
if (payload[widget.id]) {
|
.map(o => o.reason.config.errorHeader);
|
||||||
payload[widget.id].id = widget.id;
|
|
||||||
payload[widget.id].index = widget.index;
|
this.widgets.forEach((widget, i) => {
|
||||||
section.widgets[i] = payload[widget.id];
|
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]));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
} else if (payload[widget.id]) {
|
||||||
}
|
payload[widget.id].id = widget.id;
|
||||||
});
|
payload[widget.id].index = widget.index;
|
||||||
}).catch(error => {
|
this.widgets[i] = payload[widget.id];
|
||||||
// TODO(chris): revert placement on failure
|
this.originalWidgets[widget.id] = structuredClone(ObjectUtils.deepToRaw(this.widgets[i]));
|
||||||
console.error('ERROR: ', error);
|
}
|
||||||
alert('ERROR: ' + error.response.data.retval);
|
});
|
||||||
});
|
})
|
||||||
|
.catch(this.$fhcAlert.handleSystemError);
|
||||||
},
|
},
|
||||||
widgetRemove(section_name, id) {
|
widgetRemove(section_name, id) {
|
||||||
axios.post(this.apiurl + '/Config/removeWidgetFromUserOverride', {
|
this.$api
|
||||||
db: this.dashboard,
|
.call(ApiDashboardUser.removeWidget(this.dashboard, id))
|
||||||
funktion_kurzbz: section_name,
|
.then(() => {
|
||||||
widgetid: id
|
this.widgets = this.widgets.filter(widget => widget.id != id);
|
||||||
}).then(() => {
|
})
|
||||||
this.sections.forEach(section => {
|
.catch(this.$fhcAlert.handleSystemError);
|
||||||
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);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$p.loadCategory('dashboard');
|
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:{
|
this.$api
|
||||||
db: this.dashboard
|
.call(ApiDashboardWidget.listAllowed(this.dashboard))
|
||||||
}}).then(res => {
|
.then(res => {
|
||||||
for (var name in res.data.retval) {
|
this.widgetsSetup = res.data;
|
||||||
let widgets = [];
|
})
|
||||||
let remove = [];
|
.catch(this.$fhcAlert.handleSystemError);
|
||||||
for (var wid in res.data.retval[name].widgets) {
|
|
||||||
res.data.retval[name].widgets[wid].id = wid;
|
this.$api
|
||||||
if (res.data.retval[name].widgets[wid].custom || res.data.retval[name].widgets[wid].preset)
|
.call(ApiDashboardUser.get(this.dashboard))
|
||||||
widgets.push(res.data.retval[name].widgets[wid]);
|
.then(res => {
|
||||||
else
|
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);
|
remove.push(wid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.sections.push({
|
|
||||||
name: name,
|
remove.forEach(wid => this.widgetRemove('general', wid));
|
||||||
widgets: widgets
|
|
||||||
});
|
this.widgets = widgets;
|
||||||
remove.forEach(wid => this.widgetRemove(name, wid));
|
})
|
||||||
}
|
.catch(this.$fhcAlert.handleSystemError);
|
||||||
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
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
template: `
|
template: `
|
||||||
<div class="core-dashboard">
|
<div class="core-dashboard">
|
||||||
<h3 v-show="viewDataInternal?.name">
|
<h3>
|
||||||
{{ $p.t('global/personalGreeting', [ viewDataInternal?.name ]) }}
|
{{ $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>
|
<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>
|
</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-section :seperator="0" name="general" :widgets="widgets" @widgetAdd="widgetAdd" @widgetUpdate="widgetUpdate" @widgetRemove="widgetRemove"></dashboard-section>
|
||||||
<dashboard-widget-picker ref="widgetpicker" :widgets="widgets"></dashboard-widget-picker>
|
<dashboard-widget-picker ref="widgetpicker" :widgets="widgetsSetup"></dashboard-widget-picker>
|
||||||
</div>`
|
</div>`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import BsModal from "../Bootstrap/Modal.js";
|
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";
|
import HeightTransition from "../Tranistion/HeightTransition.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -70,6 +70,14 @@ export default {
|
|||||||
ready() {
|
ready() {
|
||||||
return this.component && this.arguments !== null;
|
return this.component && this.arguments !== null;
|
||||||
},
|
},
|
||||||
|
visible: {
|
||||||
|
get() {
|
||||||
|
return !this.hidden;
|
||||||
|
},
|
||||||
|
set(value) {
|
||||||
|
this.$emit('remove', this.hidden);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
unpin(){
|
unpin(){
|
||||||
@@ -142,8 +150,14 @@ export default {
|
|||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
const { actions } = useCachedWidgetLoader();
|
||||||
|
return {
|
||||||
|
loadWidget: actions.load
|
||||||
|
};
|
||||||
|
},
|
||||||
async created() {
|
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;
|
let component = (await import(this.widget.setup.file)).default;
|
||||||
this.$options.components["widget" + this.widget.widget_id] = component;
|
this.$options.components["widget" + this.widget.widget_id] = component;
|
||||||
this.component = "widget" + this.widget.widget_id;
|
this.component = "widget" + this.widget.widget_id;
|
||||||
@@ -185,7 +199,7 @@ export default {
|
|||||||
</a>
|
</a>
|
||||||
<Transition>
|
<Transition>
|
||||||
<div v-if="!custom && editMode" class="col-auto px-1 form-switch">
|
<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>
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import BsConfirm from "../Bootstrap/Confirm.js";
|
import BsConfirm from "../Bootstrap/Confirm.js";
|
||||||
import DropGrid from '../Drop/Grid.js'
|
import DropGrid from '../Drop/Grid.js'
|
||||||
import DashboardItem from "./Item.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"
|
import WidgetIcon from "./Widget/WidgetIcon.js"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -125,23 +125,23 @@ export default {
|
|||||||
},
|
},
|
||||||
checkResizeLimit(item, w, h) {
|
checkResizeLimit(item, w, h) {
|
||||||
// NOTE(chris): widgets needs to be loaded for this to work
|
// 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) {
|
if (widget) {
|
||||||
let minmaxW = widget.setup.width;
|
let minmaxW = { ...widget.setup.width };
|
||||||
if (minmaxW.max)
|
if (minmaxW.max)
|
||||||
minmaxW.min = minmaxW.min || 1;
|
minmaxW.min = minmaxW.min || 1;
|
||||||
else
|
else
|
||||||
minmaxW = {min:minmaxW,max:minmaxW};
|
minmaxW = { min: minmaxW, max: minmaxW };
|
||||||
if (w < minmaxW.min)
|
if (w < minmaxW.min)
|
||||||
w = minmaxW.min;
|
w = minmaxW.min;
|
||||||
if (w > minmaxW.max)
|
if (w > minmaxW.max)
|
||||||
w = minmaxW.max;
|
w = minmaxW.max;
|
||||||
|
|
||||||
let minmaxH = widget.setup.height;
|
let minmaxH = { ...widget.setup.height };
|
||||||
if (minmaxH.max)
|
if (minmaxH.max)
|
||||||
minmaxH.min = minmaxH.min || 1;
|
minmaxH.min = minmaxH.min || 1;
|
||||||
else
|
else
|
||||||
minmaxH = {min:minmaxH,max:minmaxH};
|
minmaxH = { min: minmaxH, max: minmaxH };
|
||||||
if (h < minmaxH.min)
|
if (h < minmaxH.min)
|
||||||
h = minmaxH.min;
|
h = minmaxH.min;
|
||||||
if (h > minmaxH.max)
|
if (h > minmaxH.max)
|
||||||
@@ -151,7 +151,7 @@ export default {
|
|||||||
},
|
},
|
||||||
removeWidget(item, revert) {
|
removeWidget(item, revert) {
|
||||||
if (item.custom) {
|
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 {
|
} else {
|
||||||
let update = {};
|
let update = {};
|
||||||
update[item.id] = { hidden: !revert };
|
update[item.id] = { hidden: !revert };
|
||||||
@@ -199,6 +199,13 @@ export default {
|
|||||||
this.$emit('widgetUpdate', this.name, payload);
|
this.$emit('widgetUpdate', this.name, payload);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
setup() {
|
||||||
|
const { state: widgetState } = useCachedWidgetLoader();
|
||||||
|
|
||||||
|
return {
|
||||||
|
widgetState
|
||||||
|
};
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
let self = this;
|
let self = this;
|
||||||
let cont = self.$refs.container;
|
let cont = self.$refs.container;
|
||||||
|
|||||||
@@ -170,6 +170,7 @@ export default {
|
|||||||
return this.$attrs.modelValue;
|
return this.$attrs.modelValue;
|
||||||
},
|
},
|
||||||
set(v) {
|
set(v) {
|
||||||
|
this.clearValidationForThisName()
|
||||||
if (!this.$attrs.hasOwnProperty('modelValue'))
|
if (!this.$attrs.hasOwnProperty('modelValue'))
|
||||||
this.modelValueDummy = v;
|
this.modelValueDummy = v;
|
||||||
this.$emit('update:modelValue', v);
|
this.$emit('update:modelValue', v);
|
||||||
@@ -242,9 +243,9 @@ export default {
|
|||||||
template: `
|
template: `
|
||||||
<component :is="!hasContainer ? 'FhcFragment' : 'div'" class="position-relative" :class="autoContainerClass">
|
<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>
|
<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)">
|
<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="clearValidationForThisName(); $emit('input', $event)"></textarea>
|
<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="clearValidationForThisName(); $emit('input', $event)">
|
<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>
|
<slot></slot>
|
||||||
</select>
|
</select>
|
||||||
<component
|
<component
|
||||||
|
|||||||
@@ -74,6 +74,16 @@ export default {
|
|||||||
],
|
],
|
||||||
'abschlussdokument_lehrgaenge.xml.php': [
|
'abschlussdokument_lehrgaenge.xml.php': [
|
||||||
'AbschlussdokumentLehrgaenge'
|
'AbschlussdokumentLehrgaenge'
|
||||||
|
],
|
||||||
|
'microcredential.xml.php' : [
|
||||||
|
'microcredentialzertifikat_1',
|
||||||
|
'microcredentialzertifikat_2',
|
||||||
|
'microcredentialzertifikat_3',
|
||||||
|
'microcredentialzertifikat_4',
|
||||||
|
'microcredential_1',
|
||||||
|
'microcredential_2',
|
||||||
|
'microcredential_3',
|
||||||
|
'microcredential_4',
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
documentDropdownObject: {}
|
documentDropdownObject: {}
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ export default {
|
|||||||
inject: {
|
inject: {
|
||||||
defaultSemester: {
|
defaultSemester: {
|
||||||
from: 'defaultSemester'
|
from: 'defaultSemester'
|
||||||
|
},
|
||||||
|
currentSemester: {
|
||||||
|
from: 'currentSemester'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -95,8 +98,9 @@ export default {
|
|||||||
this.formData.themenbereich = null;
|
this.formData.themenbereich = null;
|
||||||
this.formData.projekttyp_kurzbz = null;
|
this.formData.projekttyp_kurzbz = null;
|
||||||
this.formData.firma = null;
|
this.formData.firma = null;
|
||||||
this.formData.lehrveranstaltung_id = null;
|
// dont reset these form fields for UX reasons
|
||||||
this.formData.lehreinheit_id = null;
|
// this.formData.lehrveranstaltung_id = null;
|
||||||
|
// this.formData.lehreinheit_id = null;
|
||||||
this.formData.beginn = null;
|
this.formData.beginn = null;
|
||||||
this.formData.ende = null;
|
this.formData.ende = null;
|
||||||
this.formData.freigegeben = true;
|
this.formData.freigegeben = true;
|
||||||
@@ -109,7 +113,7 @@ export default {
|
|||||||
getFormData(newProjektarbeit, studiensemester_kurzbz, additional_lehrveranstaltung_id) {
|
getFormData(newProjektarbeit, studiensemester_kurzbz, additional_lehrveranstaltung_id) {
|
||||||
|
|
||||||
this.additional_lehrveranstaltung_id = 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.newProjektarbeit = newProjektarbeit;
|
||||||
|
|
||||||
this.$api
|
this.$api
|
||||||
|
|||||||
@@ -121,7 +121,6 @@ export default {
|
|||||||
height: 'auto',
|
height: 'auto',
|
||||||
minHeight: '100',
|
minHeight: '100',
|
||||||
selectableRows: true,
|
selectableRows: true,
|
||||||
selectableRows: 1,
|
|
||||||
index: 'betreuer_id',
|
index: 'betreuer_id',
|
||||||
persistence:{
|
persistence:{
|
||||||
columns: true, //persist column layout
|
columns: true, //persist column layout
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ export default {
|
|||||||
:mitarbeiter_uid="this.mitarbeiter_uid"
|
:mitarbeiter_uid="this.mitarbeiter_uid"
|
||||||
typeHeader="mitarbeiter"
|
typeHeader="mitarbeiter"
|
||||||
:domain="config.domain"
|
:domain="config.domain"
|
||||||
fotoEditable
|
|
||||||
@redirectToLeitung="handleSelection"
|
@redirectToLeitung="handleSelection"
|
||||||
>
|
>
|
||||||
<template #uid>{{tile_MaUid}}</template>
|
<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;
|
this.tabulatorHasSelector = true;
|
||||||
|
|
||||||
if (this.idField) {
|
if (this.idField) {
|
||||||
@@ -358,7 +358,7 @@ export const CoreFilterCmpt = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
_updateTabulator() {
|
_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.setColumns(this.filteredColumns);
|
||||||
this.tabulator.setData(this.filteredData);
|
this.tabulator.setData(this.filteredData);
|
||||||
this._setHeaderFilter()
|
this._setHeaderFilter()
|
||||||
|
|||||||
@@ -1,29 +1,36 @@
|
|||||||
let __widgets = {};
|
import ApiWidget from "../../api/factory/dashboard/widget.js";
|
||||||
let __widgetsStarted = {};
|
|
||||||
let __path = FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/dashboard/Widget';
|
|
||||||
|
|
||||||
export default {
|
const promises = Vue.ref([]);
|
||||||
getWidget(id) {
|
const stateRef = Vue.ref([]);
|
||||||
return __widgets[id];
|
const state = Vue.readonly(stateRef);
|
||||||
},
|
|
||||||
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!');
|
|
||||||
|
|
||||||
__widgetsStarted[id] = new Promise((resolve, reject) => {
|
export function useCachedWidgetLoader() {
|
||||||
axios.get(__path, {params:{id}}).then(res => {
|
const $api = Vue.inject('$api');
|
||||||
__widgets[id] = res.data.retval;
|
const $fhcAlert = Vue.inject('$fhcAlert');
|
||||||
__widgetsStarted[id] = undefined;
|
|
||||||
resolve(__widgets[id]);
|
function load(id) {
|
||||||
}).catch(error => reject(error.response.data.retval.error));
|
if (state.value[id])
|
||||||
});
|
return Promise.resolve(state.value[id]);
|
||||||
return __widgetsStarted[id];
|
|
||||||
},
|
if (!promises.value[id])
|
||||||
setPath(path) {
|
promises.value[id] = new Promise((resolve, reject) => {
|
||||||
__path = path;
|
$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
|
||||||
* Performs a deep merge of objects and returns new object. Does not modify
|
* objects (immutable) and merges arrays via concatenation.
|
||||||
* objects (immutable) and merges arrays via concatenation.
|
*
|
||||||
*
|
* @param {...object} objects - Objects to merge
|
||||||
* @param {...object} objects - Objects to merge
|
* @returns {object} New object with merged key/values
|
||||||
* @returns {object} New object with merged key/values
|
*/
|
||||||
*/
|
function mergeDeep(...objects) {
|
||||||
mergeDeep(...objects) {
|
const isObject = obj => obj && typeof obj === 'object';
|
||||||
const isObject = obj => obj && typeof obj === 'object';
|
|
||||||
|
return objects.reduce((prev, obj) => {
|
||||||
return objects.reduce((prev, obj) => {
|
Object.keys(obj).forEach(key => {
|
||||||
Object.keys(obj).forEach(key => {
|
const pVal = prev[key];
|
||||||
const pVal = prev[key];
|
const oVal = obj[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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
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(
|
fhcApiAxios.interceptors.response.use(
|
||||||
response => {
|
response => {
|
||||||
if (response.config?.errorHandling == 'off'
|
const errorConfig = get_error_handler(response.config);
|
||||||
|| response.config?.errorHandling === false
|
|
||||||
|| response.config?.errorHandling == 'fail')
|
if (!errorConfig.success)
|
||||||
return clean_return_value(response);
|
return clean_return_value(response);
|
||||||
|
|
||||||
// NOTE(chris): loop through errors
|
const errors = popHandleableErrors(errorConfig, response.data.errors);
|
||||||
if (response.data.errors)
|
|
||||||
response.data.errors = response.data.errors.filter(
|
for (var type in errors) {
|
||||||
err => (response.config[err.type + 'ErrorHandler'] || app.config.globalProperties.$api._defaultErrorHandlers[err.type])(err, response.config)
|
errorConfig.handler[type](errors[type]);
|
||||||
);
|
}
|
||||||
|
|
||||||
return clean_return_value(response);
|
return clean_return_value(response);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ require_once('dbupdate_3.4/68744_StV_settings.php');
|
|||||||
require_once('dbupdate_3.4/62889_reihungstest_ueberwachung_mit_constructor.php');
|
require_once('dbupdate_3.4/62889_reihungstest_ueberwachung_mit_constructor.php');
|
||||||
require_once('dbupdate_3.4/71399_dashboard_update_widget_paths.php');
|
require_once('dbupdate_3.4/71399_dashboard_update_widget_paths.php');
|
||||||
require_once('dbupdate_3.4/71645_studvw_messagetab_ladezeit.php');
|
require_once('dbupdate_3.4/71645_studvw_messagetab_ladezeit.php');
|
||||||
|
require_once('dbupdate_3.4/71566_studienordnungsdokument_neuer_organisationseinheitstyp_programm.php');
|
||||||
|
|
||||||
// *** Pruefung und hinzufuegen der neuen Attribute und Tabellen
|
// *** Pruefung und hinzufuegen der neuen Attribute und Tabellen
|
||||||
echo '<H2>Pruefe Tabellen und Attribute!</H2>';
|
echo '<H2>Pruefe Tabellen und Attribute!</H2>';
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
// neuen Organisationseinheittyp (Programm) als Zeile hinzufügen
|
||||||
|
if($result = @$db->db_query("SELECT 1 FROM public.tbl_organisationseinheittyp WHERE organisationseinheittyp_kurzbz= 'Programm';"))
|
||||||
|
{
|
||||||
|
if($db->db_num_rows($result) == 0)
|
||||||
|
{
|
||||||
|
$qry = "INSERT INTO public.tbl_organisationseinheittyp(organisationseinheittyp_kurzbz, beschreibung, bezeichnung) VALUES ('Programm', 'Programm', 'Programm');";
|
||||||
|
|
||||||
|
if(!$db->db_query($qry))
|
||||||
|
echo '<strong>public.tbl_organisationseinheittyp: '.$db->db_last_error().'</strong><br>';
|
||||||
|
else
|
||||||
|
echo '<br>public.tbl_organisationseinheittyp: Zeile Programm hinzugefuegt!<br>';
|
||||||
|
}
|
||||||
|
}
|
||||||
+333
-4
@@ -3903,6 +3903,172 @@ $phrases = array(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'app' => 'pep',
|
||||||
|
'category' => 'ui',
|
||||||
|
'phrase' => 'geplZeitraum',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'geplanter Zeitraum',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'planned Period',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'app' => 'pep',
|
||||||
|
'category' => 'ui',
|
||||||
|
'phrase' => 'bitteAuswaehlen',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'Bitte auswählen...',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'Please select...',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'app' => 'pep',
|
||||||
|
'category' => 'ui',
|
||||||
|
'phrase' => 'hinweisLehrende',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'Hinweis für Lehrende',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'Note for Lecturers',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'app' => 'pep',
|
||||||
|
'category' => 'ui',
|
||||||
|
'phrase' => 'lehreinheiten',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'Lehreinheiten',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'Teaching Units',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'app' => 'pep',
|
||||||
|
'category' => 'ui',
|
||||||
|
'phrase' => 'lead',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'Leitung',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'Lead',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'app' => 'pep',
|
||||||
|
'category' => 'ui',
|
||||||
|
'phrase' => 'teamlead',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'Team / Leitung',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'Team / Lead',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'app' => 'pep',
|
||||||
|
'category' => 'ui',
|
||||||
|
'phrase' => 'ausblick_lvplanung',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'Ausblick auf Ihre mögliche LV-Planung',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'Preview of Your Potential Course Planning',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
array(
|
||||||
|
'app' => 'pep',
|
||||||
|
'category' => 'ui',
|
||||||
|
'phrase' => 'detailselfoverview',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => '<b>Achtung:</b> die vorliegenden Informationen stellen eine Vorabplanung dar und sind als Anfrage an Sie gedacht. <br /><br />
|
||||||
|
Die Beauftragung der tatsächlichen Lehrveranstaltungen erfolgt durch Ihre Kompetenzfeldleitung. <br /><br />
|
||||||
|
Ihre aktuell gültigen Lehraufträge und den LV Plan des aktuellen Semesters (Termine) finden Sie wie gewohnt unter „mein CIS“ -> „LV-Plan Hauptmenü“ bzw. „Lehrauftragsverwaltung“.',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => '<b>Please note:</b> The information provided represents a preliminary planning and is intended as an inquiry to you.<br /><br />
|
||||||
|
The official assignment of the actual courses will be carried out by your Competence Field Manager.<br /><br />
|
||||||
|
Your currently valid teaching assignments and the course schedule for the current semester (dates) can be found as usual under “My CIS” → “Schedule Main Menu” or “Teaching Assignment Administration”',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
array(
|
array(
|
||||||
'app' => 'pep',
|
'app' => 'pep',
|
||||||
'category' => 'ui',
|
'category' => 'ui',
|
||||||
@@ -44726,9 +44892,9 @@ array(
|
|||||||
'phrases' => array(
|
'phrases' => array(
|
||||||
array(
|
array(
|
||||||
'sprache' => 'German',
|
'sprache' => 'German',
|
||||||
'text' => "Für den gesamten Studiengang verbindlicher Termin.
|
'text' => "Für den gesamten Studiengang verbindlicher Termin.
|
||||||
|
|
||||||
Liegt ein Termin in der Vergangenheit, kann nichts mehr hochgeladen werden. Ist es dennoch erforderlich,
|
Liegt ein Termin in der Vergangenheit, kann nichts mehr hochgeladen werden. Ist es dennoch erforderlich,
|
||||||
haben Studierende bei der Studiengangsassistenz um eine Korrektur dieses Termins anzusuchen.",
|
haben Studierende bei der Studiengangsassistenz um eine Korrektur dieses Termins anzusuchen.",
|
||||||
'description' => '',
|
'description' => '',
|
||||||
'insertvon' => 'system'
|
'insertvon' => 'system'
|
||||||
@@ -44919,7 +45085,7 @@ array(
|
|||||||
array(
|
array(
|
||||||
'sprache' => 'German',
|
'sprache' => 'German',
|
||||||
'text' => "Verspätete Projektabgabe ist bei Terminen, welche von der Studiengangsassistenz für den gesamten Studiengang fixiert wurden nicht erlaubt!
|
'text' => "Verspätete Projektabgabe ist bei Terminen, welche von der Studiengangsassistenz für den gesamten Studiengang fixiert wurden nicht erlaubt!
|
||||||
|
|
||||||
Um einen Endupload durchführen zu können, müssen Sie ein positiv benotetes Quality Gate 1 & Quality Gate 2 in der relevanten Projektarbeit absolviert haben.",
|
Um einen Endupload durchführen zu können, müssen Sie ein positiv benotetes Quality Gate 1 & Quality Gate 2 in der relevanten Projektarbeit absolviert haben.",
|
||||||
'description' => '',
|
'description' => '',
|
||||||
'insertvon' => 'system'
|
'insertvon' => 'system'
|
||||||
@@ -45234,6 +45400,46 @@ array(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'app' => 'core',
|
||||||
|
'category' => 'abgabetool',
|
||||||
|
'phrase' => 'c4downloadLatestAbgabe',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => "Zuletzt getätigte Abgabe herunterladen",
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'Download latest uploaded File',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'app' => 'core',
|
||||||
|
'category' => 'abgabetool',
|
||||||
|
'phrase' => 'c4termineTimeLine',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'Zeitstrahl Termine',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'Timeline Deadlines',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
array(
|
array(
|
||||||
'app' => 'core',
|
'app' => 'core',
|
||||||
'category' => 'abgabetool',
|
'category' => 'abgabetool',
|
||||||
@@ -46695,6 +46901,26 @@ array(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
array(
|
||||||
|
'app' => 'core',
|
||||||
|
'category' => 'abgabetool',
|
||||||
|
'phrase' => 'c4noZuordnungBetreuerStudent',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'Keine Zuordnung oder Berechtigung für die Projektarbeit gefunden!',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'No assignment or authorization found for the project!',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
// ABGABETOOL PHRASEN END
|
// ABGABETOOL PHRASEN END
|
||||||
array(
|
array(
|
||||||
'app' => 'core',
|
'app' => 'core',
|
||||||
@@ -56948,6 +57174,109 @@ I have been informed that I am under no obligation to consent to the transmissio
|
|||||||
)
|
)
|
||||||
),
|
),
|
||||||
// ### Refactor Messages END
|
// ### Refactor Messages END
|
||||||
|
//
|
||||||
|
array(
|
||||||
|
'app' => 'core',
|
||||||
|
'category' => 'stv',
|
||||||
|
'phrase' => 'error_noLehrverbandAssigned',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'StudentIn ist in diesem Semester keinem Lehrverband zugeteilt',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'Student has no assignment to any teaching association',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
// ### Phrases Dashboard Admin START
|
||||||
|
array(
|
||||||
|
'app' => 'core',
|
||||||
|
'category' => 'ui',
|
||||||
|
'phrase' => 'deleteInfo',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'Mit dieser Aktion werden auch alle Voreinstellungen der verbundenen Widgets gelöscht.',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'This action will also delete all presets of the connected widgets.',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'app' => 'core',
|
||||||
|
'category' => 'dashboard',
|
||||||
|
'phrase' => 'success_savePreset',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'Voreinstellung erfolgreich aktualisiert',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'Preset successfully updated',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
), array(
|
||||||
|
'app' => 'core',
|
||||||
|
'category' => 'dashboard',
|
||||||
|
'phrase' => 'alert_deleteWidget',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'Sind Sie sicher, dass Sie dieses Widget löschen möchten?',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'Are you sure you want to delete this widget?',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'app' => 'core',
|
||||||
|
'category' => 'ui',
|
||||||
|
'phrase' => 'confirm_delete',
|
||||||
|
'insertvon' => 'system',
|
||||||
|
'phrases' => array(
|
||||||
|
array(
|
||||||
|
'sprache' => 'German',
|
||||||
|
'text' => 'Möchten Sie wirklich löschen?',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'sprache' => 'English',
|
||||||
|
'text' => 'Do you really want to delete?',
|
||||||
|
'description' => '',
|
||||||
|
'insertvon' => 'system'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
// ### Phrases Dashboard Admin END
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -875,7 +875,6 @@ function _getLehrecontainer($sws_proStg_arr)
|
|||||||
$sws_proStg_arr = array_filter($sws_proStg_arr, function ($obj) {
|
$sws_proStg_arr = array_filter($sws_proStg_arr, function ($obj) {
|
||||||
return
|
return
|
||||||
!in_array($obj->studiengang_kz, BIS_EXCLUDE_STG) &&
|
!in_array($obj->studiengang_kz, BIS_EXCLUDE_STG) &&
|
||||||
$obj->studiengang_kz > 0 &&
|
|
||||||
$obj->studiengang_kz < 10000;
|
$obj->studiengang_kz < 10000;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -886,13 +885,17 @@ function _getLehrecontainer($sws_proStg_arr)
|
|||||||
{
|
{
|
||||||
$is_sommersemester = substr($sws_proStg->studiensemester_kurzbz, 0, 2) == 'SS';
|
$is_sommersemester = substr($sws_proStg->studiensemester_kurzbz, 0, 2) == 'SS';
|
||||||
$is_wintersemester = substr($sws_proStg->studiensemester_kurzbz, 0, 2) == 'WS';
|
$is_wintersemester = substr($sws_proStg->studiensemester_kurzbz, 0, 2) == 'WS';
|
||||||
|
$is_lehrgang = isset($sws_proStg->lgartcode);
|
||||||
|
$kennzeichen_name = $is_lehrgang ? 'LehrgangNr' : 'StgKz';
|
||||||
|
|
||||||
// Lehreobjekt generieren
|
// Lehreobjekt generieren
|
||||||
if (empty($lehre_arr) || !lehre_stg_exists($sws_proStg->studiengang_kz, $lehre_arr))
|
if (empty($lehre_arr) || !lehre_stg_exists($sws_proStg->studiengang_kz, $lehre_arr))
|
||||||
{
|
{
|
||||||
$lehre_obj = new StdClass();
|
$lehre_obj = new StdClass();
|
||||||
|
|
||||||
$lehre_obj->StgKz = setLeadingZero(intval($sws_proStg->studiengang_kz), 4);
|
$lehre_obj->{$kennzeichen_name} = $sws_proStg->melde_studiengang_kz;
|
||||||
|
//~ $lehre_obj->StgKz = setLeadingZero(intval($sws_proStg->studiengang_kz), 4);
|
||||||
|
|
||||||
$lehre_obj->SommersemesterSWS = $is_sommersemester ? $sws_proStg->sws : 0.00;
|
$lehre_obj->SommersemesterSWS = $is_sommersemester ? $sws_proStg->sws : 0.00;
|
||||||
$lehre_obj->WintersemesterSWS = $is_wintersemester ? $sws_proStg->sws : 0.00;
|
$lehre_obj->WintersemesterSWS = $is_wintersemester ? $sws_proStg->sws : 0.00;
|
||||||
|
|
||||||
@@ -1020,9 +1023,14 @@ function _generateXML($person_arr)
|
|||||||
foreach ($person->lehre_arr as $lehre)
|
foreach ($person->lehre_arr as $lehre)
|
||||||
{
|
{
|
||||||
$xml .= '<Lehre>';
|
$xml .= '<Lehre>';
|
||||||
$xml .= '<StgKz><![CDATA['. $lehre->StgKz. ']]></StgKz>';
|
|
||||||
$xml .= '<SommersemesterSWS><![CDATA['. $lehre->SommersemesterSWS. ']]></SommersemesterSWS>';
|
if (isset($lehre->LehrgangNr))
|
||||||
$xml .= '<WintersemesterSWS><![CDATA['. $lehre->WintersemesterSWS. ']]></WintersemesterSWS>';
|
$xml .= '<LehrgangNr><![CDATA['. $lehre->LehrgangNr. ']]></LehrgangNr>';
|
||||||
|
else
|
||||||
|
$xml .= '<StgKz><![CDATA['. $lehre->StgKz. ']]></StgKz>';
|
||||||
|
|
||||||
|
$xml .= '<SommersemesterSWS><![CDATA['. number_format($lehre->SommersemesterSWS, 2, '.', ''). ']]></SommersemesterSWS>';
|
||||||
|
$xml .= '<WintersemesterSWS><![CDATA['. number_format($lehre->WintersemesterSWS, 2, '.', ''). ']]></WintersemesterSWS>';
|
||||||
$xml .= '</Lehre>';
|
$xml .= '</Lehre>';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1211,7 +1219,7 @@ function _outputHTML($person_arr)
|
|||||||
{
|
{
|
||||||
echo '
|
echo '
|
||||||
<tr>
|
<tr>
|
||||||
<td>'. $lehre->StgKz. '</td>
|
<td>'. (isset($lehre->LehrgangNr) ? $lehre->LehrgangNr : $lehre->StgKz). '</td>
|
||||||
<td>'. $lehre->SommersemesterSWS. '</td>
|
<td>'. $lehre->SommersemesterSWS. '</td>
|
||||||
<td>'. $lehre->WintersemesterSWS. '</td>
|
<td>'. $lehre->WintersemesterSWS. '</td>
|
||||||
</tr>';
|
</tr>';
|
||||||
@@ -1359,7 +1367,8 @@ function lehre_stg_exists($studiengang_kz, $lehre_arr)
|
|||||||
{
|
{
|
||||||
foreach($lehre_arr as $row)
|
foreach($lehre_arr as $row)
|
||||||
{
|
{
|
||||||
if($row->StgKz == $studiengang_kz)
|
$kennzeichenName = $row->LehrgangNr ?? $row->StgKz;
|
||||||
|
if(isset($row->{$kennzeichenName}) && $row->{$kennzeichenName} == $melde_studiengang_kz)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user