mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 12:19:28 +00:00
Compare commits
109 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6019489ef1 | |||
| fc79f92796 | |||
| 8e569a9ccd | |||
| d7b2964e4e | |||
| b0f90cafb6 | |||
| d56d1bc2bd | |||
| 45eca862ac | |||
| 9f738f4871 | |||
| 3533a3fd4b | |||
| 672acfe8fe | |||
| 6a4db90897 | |||
| 82587a70be | |||
| d0ef9ca96c | |||
| a5d5d42ba3 | |||
| 15441a46f7 | |||
| a9a56bb1e9 | |||
| e840be84eb | |||
| 0b40455e3c | |||
| d9ea5a95af | |||
| 23502d4fab | |||
| 3690babf62 | |||
| 9ca7ff73f4 | |||
| c56064d189 | |||
| 424495c636 | |||
| 9c7e98f1cb | |||
| 23edcf3aa7 | |||
| ca19306b72 | |||
| 66c0c14748 | |||
| cffa493984 | |||
| 9030cdcc76 | |||
| c3ef487a6f | |||
| ac0eddf4c7 | |||
| e373e797f4 | |||
| 382244035b | |||
| b9c8c71274 | |||
| e86e7f0bd8 | |||
| c36f259571 | |||
| 501bae585a | |||
| 2c72f704d0 | |||
| 194de7b4e7 | |||
| c03609142b | |||
| 5374f71732 | |||
| c53d451000 | |||
| f6747713a1 | |||
| 59ddf175ed | |||
| ccd8d5f871 | |||
| bd47ad2b8c | |||
| e90019cdd8 | |||
| be508c99ea | |||
| 71a77fc576 | |||
| a028297da6 | |||
| ac44b36b59 | |||
| 5a6d20f817 | |||
| ce5da22180 | |||
| 05b2c3c42b | |||
| 2dd732b924 | |||
| 110f73e622 | |||
| bb0d118284 | |||
| 701ccadff3 | |||
| 34555504df | |||
| d1f5220925 | |||
| decd514b22 | |||
| 6cf7093293 | |||
| 17f11fa871 | |||
| 96812868a4 | |||
| 40c79158f7 | |||
| 054663ee00 | |||
| 81eee814e9 | |||
| 390a3c0d5a | |||
| 695dd655c0 | |||
| c34ffedb42 | |||
| b5382b1bdf | |||
| 519cbc7601 | |||
| 957da460a6 | |||
| 8f9f447acf | |||
| 2cee36d7b5 | |||
| 43925e3088 | |||
| 1c236cce02 | |||
| 4956a517ca | |||
| d9c7df736c | |||
| 73244df019 | |||
| 91d24ebae8 | |||
| 6861e26ed6 | |||
| 34242e12ea | |||
| bd67e41aa6 | |||
| 601c6c53e7 | |||
| b7ba740a3a | |||
| a6167583a3 | |||
| 1e68eb0b90 | |||
| 332efd4106 | |||
| f303191c54 | |||
| d6c7f16ceb | |||
| f1912fe739 | |||
| 2f7fe05d21 | |||
| ee4b61f549 | |||
| 511a4256bc | |||
| 3c9db86df2 | |||
| 367204a1ee | |||
| bbe55a75ea | |||
| e58bf3a8cf | |||
| 1f2f866c61 | |||
| 6ccbc95697 | |||
| 52d9e0a195 | |||
| 6a3982347b | |||
| fe7feeb74e | |||
| b2419beca6 | |||
| b752b475d9 | |||
| 658fe79ad7 | |||
| 5bbf05ac8a |
@@ -23,6 +23,15 @@ Events::on('loadRenderers', function ($renderers) {
|
||||
);
|
||||
});
|
||||
|
||||
Events::on('loadRenderers', function ($renderers) {
|
||||
$fhc_core_renderers =& $renderers();
|
||||
$fhc_core_renderers["slot_room"] = array(
|
||||
'modalTitle' => APP_ROOT.'public/js/components/Cis/Renderer/Slot/roomModalTitle.js',
|
||||
'modalContent' => APP_ROOT.'public/js/components/Cis/Renderer/Slot/roomModalContent.js',
|
||||
'calendarEventStyles' => APP_ROOT.'public/css/Cis4/CoreCalendarEvents.css'
|
||||
);
|
||||
});
|
||||
|
||||
Events::on('loadRenderers', function ($renderers) {
|
||||
$fhc_core_renderers =& $renderers();
|
||||
$fhc_core_renderers["ferien"] = array(
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
if (!defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
// 'entschuldigt' & 'noch nicht eingetragen' -> wirken sich nicht auf Antritte aus
|
||||
$config['NOTEN_OHNE_ANTRITT'] = [9, 17]; // tbl_note pk
|
||||
@@ -67,6 +67,7 @@ $route['Cis/MyLv/.*'] = 'Cis/MyLv/index/$1';
|
||||
$route['Cis/OtherLvPlan/.*'] = 'Cis/OtherLvPlan/index/$1';
|
||||
//Route for LV Plan Stg/Semester/Verband/Gruppe
|
||||
$route['Cis/StgOrgLvPlan/.*'] = 'Cis/StgOrgLvPlan/index/$1';
|
||||
$route['Cis/Benotungstool/.*'] = 'Cis/Benotungstool/index/$1';
|
||||
|
||||
$route['Abgabetool/Assistenz'] = 'Cis/Abgabetool/Assistenz';
|
||||
$route['Abgabetool/Assistenz/(:any)'] = 'Cis/Abgabetool/Assistenz/$1';
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Benotungstool extends Auth_Controller
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'index' => self::PERM_LOGGED
|
||||
]);
|
||||
|
||||
$this->_ci =& get_instance();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$viewData = array(
|
||||
'uid'=>getAuthUID(),
|
||||
);
|
||||
|
||||
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Benotungstool']);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class ProjektabgabeUebersicht extends Auth_Controller
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'index' => ['basis/cis:r']
|
||||
]);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->load->view('CisRouterView/CisRouterView.php', ['route' => 'ProjektabgabeUebersicht']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class Zeitsperren extends Auth_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'index' => ['basis/cis:r'],
|
||||
]);
|
||||
|
||||
// Load Libraries
|
||||
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* index loads the view Zeitsperren
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$viewData = array(
|
||||
'uid'=>getAuthUID(),
|
||||
);
|
||||
|
||||
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'zeitsperren']);
|
||||
}
|
||||
}
|
||||
@@ -18,18 +18,9 @@
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
//require_once('../../../include/studiengang.class.php');
|
||||
//require_once('../../../include/student.class.php');
|
||||
//require_once('../../../include/datum.class.php');
|
||||
//require_once('../../../include/mail.class.php');
|
||||
//require_once('../../../include/benutzerberechtigung.class.php');
|
||||
//require_once('../../../include/phrasen.class.php');
|
||||
//require_once('../../../include/projektarbeit.class.php');
|
||||
//require_once('../../../include/projektbetreuer.class.php');
|
||||
|
||||
class Lehre extends FHCAPI_Controller
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Object initialization
|
||||
*/
|
||||
@@ -40,38 +31,56 @@ class Lehre extends FHCAPI_Controller
|
||||
'LV' => self::PERM_LOGGED,
|
||||
'Pruefungen' => self::PERM_LOGGED,
|
||||
'semesterAverageGrade' => self::PERM_LOGGED,
|
||||
'getZugewieseneLv' => self::PERM_LOGGED,
|
||||
'getLeForLv' => self::PERM_LOGGED
|
||||
]);
|
||||
|
||||
|
||||
$this->load->library('PhrasesLib');
|
||||
|
||||
$this->loadPhrases(
|
||||
array(
|
||||
'global',
|
||||
'ui',
|
||||
'abgabetool'
|
||||
)
|
||||
);
|
||||
|
||||
$this->load->helper('hlp_sancho_helper');
|
||||
|
||||
require_once(FHCPATH . 'include/studiengang.class.php');
|
||||
require_once(FHCPATH . 'include/student.class.php');
|
||||
require_once(FHCPATH . 'include/projektarbeit.class.php');
|
||||
require_once(FHCPATH . 'include/projektbetreuer.class.php');
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
/**
|
||||
* constructs the emails of the groups from a lehrveranstaltung
|
||||
*/
|
||||
public function lvStudentenMail()
|
||||
public function lvStudentenMail()
|
||||
{
|
||||
$lehreinheit_id = $this->input->get("lehreinheit_id",TRUE);
|
||||
|
||||
// return early if the required parameter is missing
|
||||
if(!isset($lehreinheit_id))
|
||||
{
|
||||
$this->terminateWithError('Missing required parameter', self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$lehreinheit_id = $this->input->get("lehreinheit_id",TRUE);
|
||||
|
||||
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
|
||||
|
||||
$studentenMails = $this->LehreinheitModel->getStudentenMail($lehreinheit_id);
|
||||
// return early if the required parameter is missing
|
||||
if(!isset($lehreinheit_id))
|
||||
{
|
||||
$this->terminateWithError('Missing required parameter', self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
$studentenMails = $this->getDataOrTerminateWithError($studentenMails);
|
||||
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
|
||||
|
||||
$studentenMails = $this->LehreinheitModel->getStudentenMail($lehreinheit_id);
|
||||
|
||||
$studentenMails = $this->getDataOrTerminateWithError($studentenMails);
|
||||
|
||||
//convert array of objects into array of strings
|
||||
$studentenMails = array_map(function($element){
|
||||
return $element->mail;
|
||||
}, $studentenMails);
|
||||
|
||||
$this->terminateWithSuccess($studentenMails);
|
||||
$this->terminateWithSuccess($studentenMails);
|
||||
}
|
||||
|
||||
public function LV($studiensemester_kurzbz, $lehrveranstaltung_id)
|
||||
@@ -81,13 +90,13 @@ class Lehre extends FHCAPI_Controller
|
||||
$result = $this->LehrveranstaltungModel->getLvsByStudentWithGrades(getAuthUID(), $studiensemester_kurzbz, getUserLanguage(), $lehrveranstaltung_id);
|
||||
|
||||
$result = current($this->getDataOrTerminateWithError($result));
|
||||
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches all Pruefungen of a student for a specific lehrveranstaltung
|
||||
* if the student passed the Pruefung on the first attempt, no information about the Pruefungen is stored in the database
|
||||
* if the student passed the Pruefung on the first attempt, no information about the Pruefungen is stored in the database
|
||||
* @param mixed $lehrveranstaltung_id
|
||||
* @return void
|
||||
*/
|
||||
@@ -145,5 +154,46 @@ class Lehre extends FHCAPI_Controller
|
||||
|
||||
$this->terminateWithSuccess(['average_grade' => $averageGrade, 'weighted_average_grade' => $weightedAverageGrade]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches all assigned lehrveranstaltungen of a mitarbeiter for a given semester
|
||||
* @param mixed $uid
|
||||
* @param mixed $sem_kurzbz
|
||||
* @return void
|
||||
*/
|
||||
public function getZugewieseneLv() {
|
||||
$uid = $this->input->get("uid",TRUE);
|
||||
$sem_kurzbz = $this->input->get("sem_kurzbz",TRUE);
|
||||
|
||||
// TODO: error messages
|
||||
|
||||
if(!isset($sem_kurzbz) || isEmptyString($sem_kurzbz))
|
||||
$this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general');
|
||||
|
||||
if (!isset($uid) || isEmptyString($uid))
|
||||
$uid = getAuthUID();
|
||||
|
||||
// querying other ma_uids data requires admin permission
|
||||
if($uid !== getAuthUID()) {
|
||||
$this->load->library('PermissionLib');
|
||||
$isAdmin = $this->permissionlib->isBerechtigt('admin');
|
||||
if(!$isAdmin) $this->terminateWithError($this->p->t('ui', 'keineBerechtigung'), 'general');
|
||||
}
|
||||
|
||||
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
|
||||
$result = $this->LehrveranstaltungModel->getLvForLektorInSemester($sem_kurzbz, $uid);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
|
||||
public function getLeForLv() {
|
||||
$lv_id = $this->input->get("lv_id",TRUE);
|
||||
$sem_kurzbz = $this->input->get("sem_kurzbz",TRUE);
|
||||
|
||||
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
|
||||
|
||||
// $this->terminateWithSuccess($this->LehreinheitModel->getLesForLv($lv_id, $sem_kurzbz));
|
||||
$this->terminateWithSuccess($this->LehreinheitModel->getAllLehreinheitenForLvaAndMaUid($lv_id, getAuthUID(), $sem_kurzbz));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@ class LvMenu extends FHCAPI_Controller
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getLvMenu' => self::PERM_LOGGED
|
||||
'getLvMenu' => self::PERM_LOGGED,
|
||||
'getMultipleLvMenu' => self::PERM_LOGGED
|
||||
]);
|
||||
|
||||
$this->load->model("ressource/Mitarbeiter_model");
|
||||
@@ -61,24 +62,23 @@ class LvMenu extends FHCAPI_Controller
|
||||
|
||||
/**
|
||||
* alternative function to get multiple lvMenus with a single http request
|
||||
* not yet working as intended as the menu_lv.inc.php scripts called by the
|
||||
* lvMenuBuild event have logic coupled to require_once import which results in
|
||||
* a wrong logic after the first invocation -> faulty results for lvinfo, moodle
|
||||
* and several others
|
||||
*/
|
||||
public function getMultipleLvMenu($lvMenuOptionList){
|
||||
public function getMultipleLvMenu(){
|
||||
$lvMenuOptionList = $this->input->post('lvMenuOptionList', true);
|
||||
$result =[];
|
||||
foreach($lvMenuOptionList as $lvMenuOptions){
|
||||
$lvMenu = $this->getLvMenu($lvMenuOptions['lvid'],$lvMenuOptions['studiensemester_kurzbz']);
|
||||
if(isError($lvMenu)){
|
||||
// TODO: some lvMenu threw an error, handle error here
|
||||
}
|
||||
$lvMenu = $this->getLvMenuInternal($lvMenuOptions['lvid'],$lvMenuOptions['studiensemester_kurzbz']);
|
||||
|
||||
$result[$lvMenuOptions['lvid']]=$lvMenu;
|
||||
}
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function getLvMenu($lvid, $studiensemester_kurzbz)
|
||||
{
|
||||
|
||||
private function getLvMenuInternal($lvid, $studiensemester_kurzbz) {
|
||||
|
||||
// return early if parameters are missing
|
||||
if(!isset($lvid) || !isset($studiensemester_kurzbz))
|
||||
@@ -89,14 +89,14 @@ class LvMenu extends FHCAPI_Controller
|
||||
|
||||
// get the user
|
||||
if (!$user=getAuthUID())
|
||||
$this->terminateWithError($this->p->t('global', 'nichtAngemeldet'));
|
||||
$this->terminateWithError($this->p->t('global', 'nichtAngemeldet'));
|
||||
|
||||
// check if is_lector
|
||||
$is_lector = false;
|
||||
$mares = $this->Mitarbeiter_model->isMitarbeiter($user);
|
||||
if(hasData($mares))
|
||||
{
|
||||
$is_lector = getData($mares);
|
||||
$is_lector = getData($mares);
|
||||
}
|
||||
|
||||
// definition of user_is_allowed_to_upload
|
||||
@@ -105,7 +105,7 @@ class LvMenu extends FHCAPI_Controller
|
||||
|
||||
// load lehrveranstaltung
|
||||
$lvres = $this->Lehrveranstaltung_model->load($lvid);
|
||||
if(!hasData($lvres))
|
||||
if(!hasData($lvres))
|
||||
{
|
||||
$this->terminateWithError('LV ' . $lvid . ' not found.');
|
||||
}
|
||||
@@ -124,7 +124,7 @@ class LvMenu extends FHCAPI_Controller
|
||||
$stgres = $this->Studiengang_model->load(strval($studiengang_kz));
|
||||
if(!hasData($stgres))
|
||||
{
|
||||
$this->terminateWithError('Stg ' . $lv->studiengang_kz . ' not found.');
|
||||
$this->terminateWithError('Stg ' . $lv->studiengang_kz . ' not found.');
|
||||
}
|
||||
$stg = (getData($stgres))[0];
|
||||
$kurzbz = strtoupper($stg->typ . $stg->kurzbz);
|
||||
@@ -139,7 +139,7 @@ class LvMenu extends FHCAPI_Controller
|
||||
$angemeldet = false;
|
||||
|
||||
$lesres = $this->Lehreinheit_model->getLehreinheitenForStudentAndStudienSemester(
|
||||
$lvid, $user, $angezeigtes_stsem
|
||||
$lvid, $user, $angezeigtes_stsem
|
||||
);
|
||||
|
||||
if(hasData($lesres) && count(getData($lesres)) > 0)
|
||||
@@ -148,7 +148,7 @@ class LvMenu extends FHCAPI_Controller
|
||||
|
||||
// lehrfach
|
||||
$lehrfach_id='';
|
||||
|
||||
|
||||
if(defined('CIS_LEHRVERANSTALTUNG_LEHRFACH_ANZEIGEN') && CIS_LEHRVERANSTALTUNG_LEHRFACH_ANZEIGEN)
|
||||
{
|
||||
// Wenn der eingeloggte User zu einer der Lehreinheiten zugeteilt ist
|
||||
@@ -211,8 +211,8 @@ class LvMenu extends FHCAPI_Controller
|
||||
foreach($fbs as $row)
|
||||
{
|
||||
$lehrfach_oe_kurzbz_arr[] = $row->oe_kurzbz;
|
||||
if($this->PermissionLib->isBerechtigt('lehre', null, $row->oe_kurzbz)
|
||||
|| $this->PermissionLib->isBerechtigt('assistenz', null, $stg->oe_kurzbz))
|
||||
if($this->PermissionLib->isBerechtigt('lehre', null, $row->oe_kurzbz)
|
||||
|| $this->PermissionLib->isBerechtigt('assistenz', null, $stg->oe_kurzbz))
|
||||
{
|
||||
$user_is_allowed_to_upload=true;
|
||||
}
|
||||
@@ -224,21 +224,21 @@ class LvMenu extends FHCAPI_Controller
|
||||
$menu = array();
|
||||
|
||||
$this->fhc_menu_lvinfo($menu, $lvid, $studiengang_kz, $lektor_der_lv, $is_lector, $lehrfach_oe_kurzbz_arr);
|
||||
|
||||
|
||||
$this->fhc_menu_feedback($menu, $angemeldet, $lvid);
|
||||
|
||||
|
||||
$this->fhc_menu_gesamtnote($menu, $angemeldet, $lvid, $lv, $is_lector, $angezeigtes_stsem);
|
||||
|
||||
|
||||
$this->fhc_menu_emailStudierende($menu, $user, $angemeldet, $lvid, $angezeigtes_stsem);
|
||||
|
||||
|
||||
$this->fhc_menu_abmeldung($menu, $user, $is_lector, $lvid, $angezeigtes_stsem);
|
||||
|
||||
|
||||
$this->fhc_menu_lehretools($menu, $lvid, $angezeigtes_stsem, $sprache);
|
||||
|
||||
|
||||
$this->fhc_menu_anrechnungStudent($menu, $lvid, $angezeigtes_stsem);
|
||||
|
||||
|
||||
$this->fhc_menu_anrechnungLector($menu, $angezeigtes_stsem);
|
||||
|
||||
|
||||
|
||||
// Addons Menu Logic
|
||||
// ##########################################################################################
|
||||
@@ -272,18 +272,18 @@ class LvMenu extends FHCAPI_Controller
|
||||
'permissionLib' => &$this->PermissionLib,
|
||||
'phrasesLib' => &$this->PhrasesLib
|
||||
];
|
||||
|
||||
Events::trigger('lvMenuBuild',
|
||||
// passing $menu per reference
|
||||
function & () use (&$menu) {
|
||||
return $menu;
|
||||
},
|
||||
$params
|
||||
|
||||
Events::trigger('lvMenuBuild',
|
||||
// passing $menu per reference
|
||||
function & () use (&$menu) {
|
||||
return $menu;
|
||||
},
|
||||
$params
|
||||
);
|
||||
|
||||
// Menu sortieren
|
||||
// ##########################################################################################
|
||||
|
||||
|
||||
foreach ($menu as $key => $row){
|
||||
|
||||
// removes menu points that are not needed in the c4 lvUebersicht
|
||||
@@ -291,7 +291,7 @@ class LvMenu extends FHCAPI_Controller
|
||||
unset($menu[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// fills pos array to sort the menu
|
||||
$pos[$key] = $row['position'];
|
||||
|
||||
@@ -299,11 +299,18 @@ class LvMenu extends FHCAPI_Controller
|
||||
|
||||
array_multisort($pos, SORT_ASC, SORT_NUMERIC, $menu);
|
||||
|
||||
// HTTP response
|
||||
// ##########################################################################################
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function getLvMenu($lvid, $studiensemester_kurzbz)
|
||||
{
|
||||
$menu = $this->getLvMenuInternal($lvid, $studiensemester_kurzbz);
|
||||
|
||||
$this->terminateWithSuccess($menu);
|
||||
|
||||
}
|
||||
|
||||
private function fhc_menu_lvinfo(&$menu, $lvid, $studiengang_kz, $lektor_der_lv, $is_lector, $lehrfach_oe_kurzbz_arr){
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
class Studiensemester extends FHCAPI_Controller
|
||||
{
|
||||
|
||||
private $_ci;
|
||||
|
||||
/**
|
||||
* Object initialization
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getStudiensemester'=> self::PERM_LOGGED,
|
||||
|
||||
]);
|
||||
|
||||
$this->_ci =& get_instance();
|
||||
|
||||
$this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
|
||||
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* GET METHOD
|
||||
* returns List of all studiensemester as well as current one
|
||||
*/
|
||||
public function getStudiensemester()
|
||||
{
|
||||
$this->_ci->StudiensemesterModel->addOrder("start", "DESC");
|
||||
$result = $this->_ci->StudiensemesterModel->load();
|
||||
|
||||
$studiensemester = getData($result);
|
||||
$result = $this->_ci->StudiensemesterModel->getAkt();
|
||||
$aktuell = getData($result);
|
||||
|
||||
$this->terminateWithSuccess(array($studiensemester, $aktuell));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Private methods
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,367 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class Zeitsperren extends FHCAPI_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getZeitsperrenUser' => self::PERM_LOGGED,
|
||||
'getTypenZeitsperren' => self::PERM_LOGGED,
|
||||
'getTypenErreichbarkeit' => self::PERM_LOGGED,
|
||||
'getStunden' => self::PERM_LOGGED,
|
||||
'loadZeitsperre' => self::PERM_LOGGED,
|
||||
'add' => self::PERM_LOGGED,
|
||||
'update' => self::PERM_LOGGED,
|
||||
'delete' => self::PERM_LOGGED,
|
||||
]);
|
||||
|
||||
// Load Libraries
|
||||
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
|
||||
$this->load->library('form_validation');
|
||||
|
||||
// Load language phrases
|
||||
$this->loadPhrases([
|
||||
'ui',
|
||||
'person',
|
||||
'zeitsperren'
|
||||
]);
|
||||
|
||||
// Load models
|
||||
$this->load->model('ressource/Zeitsperre_model', 'ZeitsperreModel');
|
||||
$this->load->model('ressource/Zeitsperretyp_model', 'ZeitsperretypModel');
|
||||
$this->load->model('ressource/Erreichbarkeit_model', 'ErreichbarkeitModel');
|
||||
$this->load->model('ressource/Stunde_model', 'StundeModel');
|
||||
$this->load->model('ressource/Zeitaufzeichnung_model', 'ZeitaufzeichnungModel');
|
||||
}
|
||||
|
||||
public function getZeitsperrenUser($uid)
|
||||
{
|
||||
//check if $uid is passedUser
|
||||
$loggedInUser = getAuthUID();
|
||||
if($loggedInUser != $uid) {
|
||||
$this->load->library('PermissionLib');
|
||||
$isAdmin = $this->permissionlib->isBerechtigt('admin');
|
||||
if(!$isAdmin) {
|
||||
$this->terminateWithError($this->p->t('ui', 'noAdmin'), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
}
|
||||
|
||||
$result = $this->ZeitsperreModel->getZeitsperrenUser($uid);
|
||||
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
public function getTypenZeitsperren()
|
||||
{
|
||||
$this->ZeitsperretypModel->addOrder('beschreibung', 'ASC');
|
||||
$result = $this->ZeitsperretypModel->load();
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
public function getTypenErreichbarkeit()
|
||||
{
|
||||
$result = $this->ErreichbarkeitModel->load();
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
public function getStunden()
|
||||
{
|
||||
$this->StundeModel->addOrder('stunde', 'ASC');
|
||||
$result = $this->StundeModel->load();
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
public function loadZeitsperre($zeitsperre_id)
|
||||
{
|
||||
$this->ZeitsperreModel->addSelect(
|
||||
'campus.tbl_zeitsperre.*, typ.*,
|
||||
ma.person_id AS ma_person_id, ma.vorname AS ma_vorname, ma.nachname AS ma_nachname,
|
||||
ma.titelpre AS ma_titelpre, ma.titelpost AS ma_titelpost'
|
||||
);
|
||||
$this->ZeitsperreModel->addJoin('campus.tbl_zeitsperretyp typ', 'ON (typ.zeitsperretyp_kurzbz = campus.tbl_zeitsperre.zeitsperretyp_kurzbz)');
|
||||
$this->ZeitsperreModel->addJoin('public.tbl_benutzer ben', 'ON (ben.uid = campus.tbl_zeitsperre.vertretung_uid)', 'LEFT');
|
||||
$this->ZeitsperreModel->addJoin('public.tbl_person ma', 'ON (ma.person_id = ben.person_id)', 'LEFT');
|
||||
$result = $this->ZeitsperreModel->loadWhere(
|
||||
array('zeitsperre_id' => $zeitsperre_id)
|
||||
);
|
||||
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->terminateWithSuccess((current(getData($result)) ?: []));
|
||||
}
|
||||
|
||||
public function add($mitarbeiter_uid)
|
||||
{
|
||||
$loggedInUser = getAuthUID();
|
||||
|
||||
if($mitarbeiter_uid != $loggedInUser)
|
||||
$this->terminateWithError($this->p->t('ui', 'noPermission'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
$this->form_validation->set_rules('zeitsperretyp_kurzbz', 'Grund Zeitsperre', 'required', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Grund Zeitsperre'])
|
||||
]);
|
||||
|
||||
$this->form_validation->set_rules('vondatum', 'VonDatum', 'required|is_valid_date', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'VonDatum']),
|
||||
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VonDatum'])
|
||||
]);
|
||||
|
||||
$this->form_validation->set_rules('bisdatum', 'BisDatum', 'required|is_valid_date|callback_check_von_bis_datum|callback_check_diff_intval', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'BisDatum']),
|
||||
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'BisDatum']),
|
||||
'check_von_bis_datum' => $this->p->t('zeitsperre', 'error_VonDatumGroesserAlsBisDatum'),
|
||||
'check_diff_intval' => $this->p->t('zeitsperre', 'error_zeitraumAuffallendHoch')
|
||||
]);
|
||||
|
||||
if ($this->form_validation->run() == false)
|
||||
{
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
}
|
||||
|
||||
$bezeichnung = $this->input->post('bezeichnung');
|
||||
$vondatum = $this->input->post('vondatum');
|
||||
$vonstunde = $this->input->post('vonstunde');
|
||||
$bisdatum = $this->input->post('bisdatum');
|
||||
$bisstunde = $this->input->post('bisstunde');
|
||||
//$vonIso = $this->input->post('vonISO'); //Timestamp für Stunde
|
||||
//$bisIso = $this->input->post('bisISO'); //Timestamp für Stunde
|
||||
$erreichbarkeit_kurzbz = $this->input->post('erreichbarkeit_kurzbz');
|
||||
$vertretung_uid = $this->input->post('vertretung_uid');
|
||||
$zeitsperretyp_kurzbz = $this->input->post('zeitsperretyp_kurzbz');
|
||||
|
||||
//check if existing zeitsperre
|
||||
$result = $this->ZeitsperreModel->getSperreByDate($mitarbeiter_uid, $vondatum, $vonstunde, true);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
if(hasData($result))
|
||||
{
|
||||
$this->terminateWithError($this->p->t('zeitsperren', 'error_existingZeitsperre', ['typ'=> current($data)->zeitsperretyp_kurzbz]), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
//check if existing zeitaufzeichnung
|
||||
if(in_array($zeitsperretyp_kurzbz, Zeitsperre_model::BLOCKIERENDE_ZEITSPERREN))
|
||||
{
|
||||
$result = $this->ZeitsperreModel->existsZeitaufzeichnung($mitarbeiter_uid, $vondatum, $bisdatum);
|
||||
|
||||
if(hasData($result))
|
||||
$this->terminateWithError($this->p->t('zeitsperren', 'error_existingZeitaufzeichnung'), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
$result = $this->ZeitsperreModel->insert(
|
||||
[
|
||||
'mitarbeiter_uid' => $mitarbeiter_uid,
|
||||
'bezeichnung' => $bezeichnung,
|
||||
'vondatum' => $vondatum,
|
||||
'vonstunde' => $vonstunde,
|
||||
'bisdatum' => $bisdatum,
|
||||
'bisstunde' => $bisstunde,
|
||||
'erreichbarkeit_kurzbz' => $erreichbarkeit_kurzbz,
|
||||
'zeitsperretyp_kurzbz' => $zeitsperretyp_kurzbz,
|
||||
'vertretung_uid' => $vertretung_uid,
|
||||
'insertvon' => $loggedInUser,
|
||||
'insertamum' => date('c'),
|
||||
]
|
||||
);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
|
||||
public function update($zeitsperre_id)
|
||||
{
|
||||
//check if loggedin User is owner of the zeitsperre
|
||||
$loggedInUser = getAuthUID();
|
||||
$result = $this->ZeitsperreModel->load($zeitsperre_id);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
$uid = current($data)->mitarbeiter_uid;
|
||||
|
||||
if($uid != $loggedInUser)
|
||||
$this->terminateWithError($this->p->t('ui', 'noPermission'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
if(!$zeitsperre_id)
|
||||
{
|
||||
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Zeitsperre_id']), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
//get current params
|
||||
$array_update = [
|
||||
'bezeichnung',
|
||||
'vondatum',
|
||||
'vonstunde',
|
||||
'bisdatum',
|
||||
'bisstunde',
|
||||
// 'vonISO', //Timestamp für Stunde
|
||||
// 'bisISO', //Timestamp für Stunde
|
||||
'erreichbarkeit_kurzbz',
|
||||
'vertretung_uid',
|
||||
'zeitsperretyp_kurzbz',
|
||||
'mitarbeiter_uid',
|
||||
];
|
||||
$post = $this->input->post();
|
||||
$update = [];
|
||||
|
||||
foreach ($array_update as $prop)
|
||||
{
|
||||
if (array_key_exists($prop, $post))
|
||||
{
|
||||
$update[$prop] = $post[$prop];
|
||||
}
|
||||
}
|
||||
|
||||
// Validation
|
||||
$rulesDefined = false; //necessary, otherwise CI validation will always be triggered, even without rules
|
||||
foreach ($update as $key => $val) {
|
||||
switch ($key) {
|
||||
case 'zeitsperretyp_kurzbz':
|
||||
$this->form_validation->set_rules(
|
||||
$key,
|
||||
'Grund Zeitsperre',
|
||||
'required',
|
||||
['required' => $this->p->t('ui', 'error_fieldRequired', ['field'=>'Grund Zeitsperre'])]
|
||||
);
|
||||
$rulesDefined = true;
|
||||
break;
|
||||
case 'vondatum':
|
||||
$this->form_validation->set_rules(
|
||||
$key,
|
||||
'VonDatum',
|
||||
'required|is_valid_date',
|
||||
[
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field'=>'VonDatum']),
|
||||
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field'=>'VonDatum'])
|
||||
]
|
||||
);
|
||||
$rulesDefined = true;
|
||||
break;
|
||||
case 'bisdatum':
|
||||
$rules = 'required|is_valid_date';
|
||||
if (array_key_exists('vondatum', $update)) {
|
||||
$rules .= '|callback_check_von_bis_datum|callback_check_diff_intval';
|
||||
}
|
||||
$this->form_validation->set_rules(
|
||||
$key,
|
||||
'BisDatum',
|
||||
$rules,
|
||||
[
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field'=>'BisDatum']),
|
||||
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field'=>'BisDatum']),
|
||||
'check_von_bis_datum' => $this->p->t('zeitsperre', 'error_VonDatumGroesserAlsBisDatum'),
|
||||
'check_diff_intval' => $this->p->t('zeitsperre', 'error_zeitraumAuffallendHoch')
|
||||
]
|
||||
);
|
||||
$rulesDefined = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($rulesDefined && $this->form_validation->run() == false) {
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
}
|
||||
|
||||
if(array_key_exists('vondatum', $post) || array_key_exists('bisdatum', $post))
|
||||
{
|
||||
$result = $this->ZeitsperreModel->load($zeitsperre_id);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
$data = current($data);
|
||||
|
||||
$mitarbeiter_uid = array_key_exists('mitarbeiter_uid', $post) ? $update['mitarbeiter_uid'] : $data->mitarbeiter_uid;
|
||||
$vondatum = array_key_exists('vondatum', $post) ? $update['vondatum'] : $data->vondatum;
|
||||
$bisdatum = array_key_exists('bisdatum', $post) ? $update['bisdatum'] : $data->bisdatum;
|
||||
$vonstunde = array_key_exists('vonstunde', $post) ? $update['vonstunde'] : $data->vonstunde;
|
||||
$zeitsperretyp_kurzbz = array_key_exists('zeitsperretyp_kurzbz', $post) ? $update['zeitsperretyp_kurzbz'] : $data->zeitsperretyp_kurzbz;
|
||||
|
||||
$result = $this->ZeitsperreModel->getSperreByDate($mitarbeiter_uid, $vondatum, $vonstunde, true);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
if(hasData($result))
|
||||
{
|
||||
$this->terminateWithError($this->p->t('zeitsperren', 'error_existingZeitsperre', ['typ'=> current($data)->zeitsperretyp_kurzbz]), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
//check if existing zeitaufzeichnung
|
||||
if(in_array($zeitsperretyp_kurzbz, Zeitsperre_model::BLOCKIERENDE_ZEITSPERREN))
|
||||
{
|
||||
$result = $this->ZeitsperreModel->existsZeitaufzeichnung($mitarbeiter_uid, $vondatum, $bisdatum);
|
||||
|
||||
if(hasData($result))
|
||||
$this->terminateWithError($this->p->t('zeitsperren', 'error_existingZeitaufzeichnung'), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($update)) {
|
||||
$update['updatevon'] = $loggedInUser;
|
||||
$update['updateamum'] = date('c');
|
||||
$result = $this->ZeitsperreModel->update($zeitsperre_id, $update);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
else
|
||||
$this->terminateWithSuccess("no update");
|
||||
}
|
||||
|
||||
public function delete($zeitsperre_id)
|
||||
{
|
||||
|
||||
if (!is_numeric($zeitsperre_id) || (int)$zeitsperre_id <= 0)
|
||||
{
|
||||
$this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Zeitsperre_id']), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
//check if loggedin User is owner of the zeitsperre
|
||||
$loggedInUser = getAuthUID();
|
||||
$result = $this->ZeitsperreModel->load($zeitsperre_id);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
$uid = current($data)->mitarbeiter_uid;
|
||||
|
||||
if($uid != $loggedInUser)
|
||||
$this->terminateWithError($this->p->t('ui', 'noPermission'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
$result = $this->ZeitsperreModel->delete(
|
||||
array('zeitsperre_id' => $zeitsperre_id)
|
||||
);
|
||||
|
||||
if (isError($result)) {
|
||||
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
public function check_von_bis_datum($bisdatum)
|
||||
{
|
||||
$vondatum = $this->input->post('vondatum');
|
||||
|
||||
return $vondatum <= $bisdatum;
|
||||
}
|
||||
|
||||
public function check_diff_intval($bisdatum)
|
||||
{
|
||||
$vondatum = $this->input->post('vondatum');
|
||||
|
||||
// Intervall in days
|
||||
$vonTs = strtotime($vondatum);
|
||||
$bisTs = strtotime($bisdatum);
|
||||
|
||||
$tage = ($bisTs - $vonTs) / 86400;
|
||||
|
||||
// if intervall > 14
|
||||
return $tage <= 14;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class RoomPlan extends FHCAPI_Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Object initialization
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'addRoomReservation' => self::PERM_LOGGED,
|
||||
'deleteRoomReservation' => self::PERM_LOGGED,
|
||||
'getRoomCreationInfo' => self::PERM_LOGGED,
|
||||
'getGruppen' => self::PERM_LOGGED,
|
||||
'getLektor' => self::PERM_LOGGED,
|
||||
'getReservableMap' => self::PERM_LOGGED,
|
||||
]);
|
||||
|
||||
$this->load->library('LogLib');
|
||||
$this->loglib->setConfigs(array(
|
||||
'classIndex' => 5,
|
||||
'functionIndex' => 5,
|
||||
'lineIndex' => 4,
|
||||
'dbLogType' => 'API',
|
||||
'dbExecuteUser' => 'RESTful API'
|
||||
));
|
||||
|
||||
$this->load->library('form_validation');
|
||||
$this->load->library('PermissionLib');
|
||||
$this->load->library('StundenplanLib');
|
||||
|
||||
$this->loadPhrases(['ui']);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
|
||||
|
||||
public function addRoomReservation()
|
||||
{
|
||||
$this->form_validation->set_rules('selectedStart', "Start", "required");
|
||||
$this->form_validation->set_rules('selectedEnd', "End", "required");
|
||||
$this->form_validation->set_rules('title', "Title", "required|max_length[10]");
|
||||
$this->form_validation->set_rules('beschreibung', "Beschreibung", "required|max_length[32]");
|
||||
$this->form_validation->set_rules('ort_kurzbz', "Ort", "required|max_length[16]");
|
||||
$this->form_validation->set_rules('studiengang', 'Studiengang', 'numeric');
|
||||
$this->form_validation->set_rules('semester', 'Semester', 'integer|greater_than_equal_to[0]');
|
||||
$this->form_validation->set_rules('verband', 'Verband', 'trim');
|
||||
$this->form_validation->set_rules('gruppe', 'Gruppe', 'trim');
|
||||
$this->form_validation->set_rules('spezialgruppe', 'Spezialgruppe', 'max_length[32]');
|
||||
$this->form_validation->set_rules('lektoren', 'Lektoren');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$start = $this->input->post('selectedStart');
|
||||
$end = $this->input->post('selectedEnd');
|
||||
$title = $this->input->post('title');
|
||||
$beschreibung = $this->input->post('beschreibung');
|
||||
$ort_kurzbz = $this->input->post('ort_kurzbz');
|
||||
|
||||
$studiengang_kz = $this->input->post('studiengang');
|
||||
$semester = $this->input->post('semester');
|
||||
$verband = $this->input->post('verband');
|
||||
$gruppe = $this->input->post('gruppe');
|
||||
$spezialgruppe = $this->input->post('spezialgruppe');
|
||||
$lektoren = $this->input->post('lektoren');
|
||||
|
||||
|
||||
$result = $this->stundenplanlib->addReservation($start, $end, $title, $beschreibung, $ort_kurzbz, $lektoren, $studiengang_kz, $semester, $verband, $gruppe, $spezialgruppe);
|
||||
|
||||
if (isError($result))
|
||||
$this->terminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
|
||||
public function deleteRoomReservation()
|
||||
{
|
||||
$reservierung_id = $this->input->post('reservierung_id');
|
||||
|
||||
$result = $this->stundenplanlib->deleteReservation($reservierung_id);
|
||||
|
||||
if (isError($result))
|
||||
$this->terminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
|
||||
public function getRoomCreationInfo()
|
||||
{
|
||||
$return_array = array('berechtigt' => false, 'studiengaenge' => []);
|
||||
if (!$this->permissionlib->isBerechtigt('lehre/reservierung'))
|
||||
$this->terminateWithSuccess($return_array);
|
||||
|
||||
$stg_berechtigungen = $this->permissionlib->getSTG_isEntitledFor('lehre/reservierung');
|
||||
if (isEmptyArray($stg_berechtigungen))
|
||||
$this->terminateWithSuccess($return_array);
|
||||
|
||||
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
|
||||
$this->StudiengangModel->addSelect('studiengang_kz, UPPER(CONCAT(typ, kurzbz)) as kuerzel, kurzbzlang');
|
||||
$this->StudiengangModel->addOrder('typ, kurzbz');
|
||||
$this->StudiengangModel->db->where_in('studiengang_kz', $stg_berechtigungen);
|
||||
$studiengaenge = $this->StudiengangModel->loadWhere(array('aktiv' => true));
|
||||
|
||||
if (isError($studiengaenge))
|
||||
$this->terminateWithError($studiengaenge);
|
||||
|
||||
$return_array['studiengaenge'] = hasData($studiengaenge) ? getData($studiengaenge) : [];
|
||||
$return_array['berechtigt'] = true;
|
||||
|
||||
$this->terminateWithSuccess($return_array);
|
||||
}
|
||||
|
||||
public function getGruppen()
|
||||
{
|
||||
$query = $this->input->get('query');
|
||||
if (is_null($query))
|
||||
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
$stg_berechtigungen = $this->permissionlib->getSTG_isEntitledFor('lehre/reservierung');
|
||||
|
||||
if (isEmptyArray($stg_berechtigungen))
|
||||
$this->terminateWithSuccess([]);
|
||||
|
||||
$this->load->model('organisation/gruppe_model', 'GruppeModel');
|
||||
|
||||
$query_words = explode(' ', urldecode($query));
|
||||
|
||||
$this->GruppeModel->addOrder('gruppe_kurzbz');
|
||||
$this->GruppeModel->db->group_start();
|
||||
foreach ($query_words as $word)
|
||||
{
|
||||
$this->GruppeModel->db->group_start();
|
||||
$this->GruppeModel->db->where('gruppe_kurzbz ILIKE', "%" . $word . "%");
|
||||
$this->GruppeModel->db->or_where('bezeichnung ILIKE', "%" . $word . "%");
|
||||
$this->GruppeModel->db->or_where('beschreibung ILIKE', "%" . $word . "%");
|
||||
$this->GruppeModel->db->or_where('orgform_kurzbz ILIKE', "%" . $word . "%");
|
||||
|
||||
if (is_numeric($word))
|
||||
{
|
||||
$this->GruppeModel->db->or_where('studiengang_kz', $word);
|
||||
}
|
||||
$this->GruppeModel->db->group_end();
|
||||
}
|
||||
$this->GruppeModel->db->group_end();
|
||||
$this->GruppeModel->db->where_in('studiengang_kz', $stg_berechtigungen);
|
||||
$gruppen = $this->GruppeModel->loadWhere(array('sichtbar' => true, 'lehre' => true));
|
||||
if (isError($gruppen))
|
||||
$this->terminateWithError($gruppen);
|
||||
|
||||
$this->terminateWithSuccess(hasData($gruppen) ? getData($gruppen) : []);
|
||||
}
|
||||
|
||||
public function getLektor()
|
||||
{
|
||||
|
||||
$query = $this->input->get('query');
|
||||
if (is_null($query))
|
||||
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
$stg_berechtigungen = $this->permissionlib->getSTG_isEntitledFor('lehre/reservierung');
|
||||
|
||||
if (isEmptyArray($stg_berechtigungen))
|
||||
$this->terminateWithSuccess([]);
|
||||
|
||||
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
|
||||
|
||||
$query_words = explode(' ', urldecode($query));
|
||||
|
||||
$this->MitarbeiterModel->addSelect('uid, person_id, vorname, nachname');
|
||||
$this->MitarbeiterModel->addJoin('public.tbl_benutzer', 'uid = mitarbeiter_uid');
|
||||
$this->MitarbeiterModel->addJoin('public.tbl_person', 'person_id');
|
||||
$this->MitarbeiterModel->db->where('public.tbl_benutzer.aktiv', true);
|
||||
$this->MitarbeiterModel->db->group_start();
|
||||
foreach ($query_words as $word)
|
||||
{
|
||||
$this->MitarbeiterModel->db->group_start();
|
||||
$this->MitarbeiterModel->db->where('tbl_person.vorname ILIKE', "%" . $word . "%");
|
||||
$this->MitarbeiterModel->db->or_where('tbl_person.nachname ILIKE', "%" . $word . "%");
|
||||
$this->MitarbeiterModel->db->or_where('uid ILIKE', "%" . $word . "%");
|
||||
$this->MitarbeiterModel->db->group_end();
|
||||
}
|
||||
$this->MitarbeiterModel->db->group_end();
|
||||
|
||||
$this->MitarbeiterModel->addOrder('nachname');
|
||||
$this->MitarbeiterModel->addOrder('vorname');
|
||||
$mitarbeiter = $this->MitarbeiterModel->load();
|
||||
if (isError($mitarbeiter))
|
||||
$this->terminateWithError($mitarbeiter);
|
||||
|
||||
$this->terminateWithSuccess(hasData($mitarbeiter) ? getData($mitarbeiter) : []);
|
||||
}
|
||||
|
||||
public function getReservableMap($ort_kurzbz = null)
|
||||
{
|
||||
$this->form_validation->set_rules('start_date', "StartDate", "required");
|
||||
$this->form_validation->set_rules('end_date', "EndDate", "required");
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
// storing the post parameter in local variables
|
||||
$start_date = $this->input->post('start_date', true);
|
||||
$end_date = $this->input->post('end_date', true);
|
||||
|
||||
$result = $this->stundenplanlib->getReservableMap($ort_kurzbz, $start_date, $end_date);
|
||||
|
||||
$this->terminateWithSuccess(array('reservierbarMap' => hasData($result) ? getData($result) : []));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
<?php
|
||||
/**
|
||||
* FH-Complete
|
||||
*
|
||||
* @package FHC-API
|
||||
* @author FHC-Team
|
||||
* @copyright Copyright (c) 2016, fhcomplete.org
|
||||
* @license GPLv3
|
||||
* @link http://fhcomplete.org
|
||||
* @since Version 1.0
|
||||
* @filesource
|
||||
*/
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
if (!defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
use CI3_Events as Events;
|
||||
|
||||
class PaabgabeUebersicht extends FHCAPI_Controller
|
||||
{
|
||||
const DOWNLOAD_PERMISSION = 'lehre/abgabetool:download';
|
||||
const ABGABE_TYPES = ['Bachelor', 'Diplom'];
|
||||
|
||||
/**
|
||||
* PaabgabeUebersicht API constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'viewData' => self::PERM_LOGGED,
|
||||
'getPaAbgaben' => array('lehre/abgabetool:r'),
|
||||
'getStudiengaenge' => array('lehre/abgabetool:r'),
|
||||
'getTermine' => array('lehre/abgabetool:r'),
|
||||
'getPaAbgabetypen' => array('lehre/abgabetool:r'),
|
||||
'downloadZip' => array('lehre/abgabetool:r'),
|
||||
//'downloadProjektarbeit' => array('lehre/abgabetool:r')
|
||||
]);
|
||||
|
||||
$this->load->model('education/Paabgabe_model', 'PaabgabeModel');
|
||||
|
||||
$this->load->library('PermissionLib');
|
||||
|
||||
// Load Phrases
|
||||
$this->loadPhrases([
|
||||
'abgabetool'
|
||||
]);
|
||||
}
|
||||
|
||||
public function viewData()
|
||||
{
|
||||
$viewData = [
|
||||
"uid" => getAuthUID(),
|
||||
// TODO create permission
|
||||
"showEdit" => true,
|
||||
];
|
||||
|
||||
$this->terminateWithSuccess($viewData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Projektabgaben for search criteria.
|
||||
*/
|
||||
public function getPaAbgaben()
|
||||
{
|
||||
$studiengang_kz = $this->input->get('studiengang_kz');
|
||||
$abgabetyp_kurzbz = $this->input->get('abgabetyp_kurzbz');
|
||||
$abgabedatum = $this->input->get('abgabedatum');
|
||||
$personSearchString = $this->input->get('personSearchString');
|
||||
|
||||
$result = $this->PaabgabeModel->getPaAbgaben(self::ABGABE_TYPES, $studiengang_kz, $abgabetyp_kurzbz, $abgabedatum, $personSearchString);
|
||||
|
||||
if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
|
||||
|
||||
// check wether Abgabe is in visual library
|
||||
if (hasData($result))
|
||||
{
|
||||
Events::trigger('in_visual_library', getData($result));
|
||||
}
|
||||
|
||||
$this->terminateWithSuccess(getData($result) ?: []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Studiengänge for which user is entitled for
|
||||
*/
|
||||
public function getStudiengaenge()
|
||||
{
|
||||
$studiengang_kz_arr = $this->permissionlib->getSTG_isEntitledFor(self::DOWNLOAD_PERMISSION);
|
||||
|
||||
if (!$studiengang_kz_arr) $this->terminateWithSuccess([]);
|
||||
|
||||
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
|
||||
|
||||
$this->StudiengangModel->addSelect('tbl_studiengang.*, UPPER(tbl_studiengang.typ || tbl_studiengang.kurzbz) AS kuerzel', $studiengang_kz_arr);
|
||||
$this->StudiengangModel->db->where_in('studiengang_kz', $studiengang_kz_arr);
|
||||
$this->StudiengangModel->addOrder('typ, kurzbz');
|
||||
$result = $this->StudiengangModel->load();
|
||||
|
||||
if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
|
||||
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get projekt work due dates, depending on search criteria.
|
||||
*/
|
||||
public function getTermine()
|
||||
{
|
||||
$studiengang_kz = $this->input->get('studiengang_kz');
|
||||
$abgabetyp_kurzbz = $this->input->get('abgabetyp_kurzbz');
|
||||
|
||||
$result = $this->PaabgabeModel->getTermine(self::ABGABE_TYPES, $studiengang_kz, $abgabetyp_kurzbz);
|
||||
|
||||
if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
|
||||
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all submission types.
|
||||
*/
|
||||
public function getPaAbgabetypen()
|
||||
{
|
||||
// Load model PaabgabetypModel
|
||||
$this->load->model('education/Paabgabetyp_model', 'PaabgabetypModel');
|
||||
|
||||
$this->PaabgabetypModel->addOrder('bezeichnung');
|
||||
$result = $this->PaabgabetypModel->load();
|
||||
|
||||
if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_DB);
|
||||
|
||||
$this->terminateWithSuccess((getData($result) ?: []));
|
||||
}
|
||||
|
||||
/**
|
||||
* Download zip files with project works matching submission search criteria.
|
||||
*/
|
||||
public function downloadZip()
|
||||
{
|
||||
$studiengang_kz = $this->input->get('studiengang_kz');
|
||||
$abgabetyp_kurzbz = $this->input->get('abgabetyp_kurzbz');
|
||||
$abgabedatum = $this->input->get('abgabedatum');
|
||||
$personSearchString = $this->input->get('personSearchString');
|
||||
|
||||
if (!isset($studiengang_kz) && !isset($abgabetyp_kurzbz) && !isset($abgabedatum) && !isset($personSearchString))
|
||||
$this->terminateWithFileOutput('text/plain', $this->p->t('abgabetool', 'nichtsAusgewaehlt'));
|
||||
|
||||
$this->load->library('zip');
|
||||
|
||||
$result = $this->PaabgabeModel->getPaAbgaben(self::ABGABE_TYPES, $studiengang_kz, $abgabetyp_kurzbz, $abgabedatum, $personSearchString);
|
||||
|
||||
if (isError($result)) $this->terminateWithFileOutput('text/plain', getError($result));
|
||||
|
||||
$fileExists = false;
|
||||
$studiengang_kuerzel = null;
|
||||
|
||||
if (!hasData($result)) $this->terminateWithFileOutput('text/plain', $this->p->t('abgabetool', 'keineDateienVorhanden'));
|
||||
|
||||
$abgaben = getData($result);
|
||||
|
||||
foreach ($abgaben as $abgabe)
|
||||
{
|
||||
$path = PAABGABE_PATH.$abgabe->paabgabe_id.'_'.$abgabe->uid.'.pdf';
|
||||
if (file_exists($path))
|
||||
{
|
||||
$fileExists = true;
|
||||
$studiengang_kuerzel = $abgabe->studiengang_kuerzel;
|
||||
$this->zip->read_file($path);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$fileExists) $this->terminateWithFileOutput('text/plain', $this->p->t('abgabetool', 'keineDateienVorhanden'));
|
||||
|
||||
$studiengang_kz = $this->input->get('studiengang_kz');
|
||||
$zipFileName = 'Abgabe'.(isset($studiengang_kz) && isset($studiengang_kuerzel) ? '_'.$studiengang_kuerzel : '').'.zip';
|
||||
$this->zip->download($zipFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Download Projektarbeit document.
|
||||
*/
|
||||
//~ public function downloadProjektarbeit()
|
||||
//~ {
|
||||
//~ $paabgabe_id = $this->input->get('paabgabe_id');
|
||||
|
||||
//~ if (!is_numeric($paabgabe_id))
|
||||
//~ $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Abgabe ID']), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
//~ //$abgabeRes = $this->PaabgabeModel->getEndabgabe($projektarbeit_id);
|
||||
//~ $this->PaabgabeModel->addSelect("paabgabe_id, student_uid, tbl_paabgabe.datum, tbl_paabgabe.abgabedatum, projekttyp_kurzbz, titel, titel_english,
|
||||
//~ paabgabe_id || '_' || student_uid || '.pdf' AS filename");
|
||||
//~ $this->PaabgabeModel->addJoin('lehre.tbl_projektarbeit', 'projektarbeit_id');
|
||||
//~ $abgabeRes = $this->PaabgabeModel->load($paabgabe_id);
|
||||
|
||||
//~ if (isError($abgabeRes))
|
||||
//~ show_error(getError($abgabeRes));
|
||||
|
||||
//~ if (hasData($abgabeRes))
|
||||
//~ {
|
||||
//~ $endabgabe = getData($abgabeRes)[0];
|
||||
//~ $filepath = PAABGABE_PATH.$endabgabe->filename;
|
||||
|
||||
//~ if (file_exists($filepath))
|
||||
//~ {
|
||||
//~ $this->output
|
||||
//~ ->set_status_header(200)
|
||||
//~ ->set_content_type('application/pdf', 'utf-8')
|
||||
//~ ->set_header('Content-Disposition: attachment; filename="'.$endabgabe->filename.'"')
|
||||
//~ ->set_output(file_get_contents($filepath))
|
||||
//~ ->_display();
|
||||
//~ }
|
||||
//~ else
|
||||
//~ {
|
||||
//~ show_error("File does not exist.");
|
||||
//~ }
|
||||
//~ }
|
||||
//~ }
|
||||
}
|
||||
@@ -13,12 +13,13 @@ class Mylv extends Auth_Controller
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
parent::__construct([
|
||||
'Student' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions?
|
||||
'Studiensemester' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions?
|
||||
'Lvs' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions?
|
||||
'Info' => ['student/anrechnung_beantragen:r','user:r'], // TODO(chris): permissions?
|
||||
'Pruefungen' => ['student/anrechnung_beantragen:r','user:r'] // TODO(chris): permissions?
|
||||
'Student' => ['student/anrechnung_beantragen:r','user:r', 'basis/cis:r'], // TODO(chris): permissions?
|
||||
'Studiensemester' => ['student/anrechnung_beantragen:r','user:r', 'basis/cis:r'], // TODO(chris): permissions?
|
||||
'Lvs' => ['student/anrechnung_beantragen:r','user:r', 'basis/cis:r'], // TODO(chris): permissions?
|
||||
'Info' => ['student/anrechnung_beantragen:r','user:r', 'basis/cis:r'], // TODO(chris): permissions?
|
||||
'Pruefungen' => ['student/anrechnung_beantragen:r','user:r', 'basis/cis:r'] // TODO(chris): permissions?
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -44,13 +45,27 @@ class Mylv extends Auth_Controller
|
||||
public function Studiensemester()
|
||||
{
|
||||
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
|
||||
$this->load->model('crm/Student_model', 'StudentModel');
|
||||
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
|
||||
|
||||
$result = $this->StudiensemesterModel->getWhereStudentHasLvs(getAuthUID());
|
||||
$isMitarbeiter = getData($this->MitarbeiterModel->isMitarbeiter(getAuthUID())) ?? false;
|
||||
if($isMitarbeiter) {
|
||||
$result = $this->StudiensemesterModel->getWhereMitarbeiterHasLvs(getAuthUID());
|
||||
|
||||
if (isError($result))
|
||||
return $this->outputJsonError(getError($result));
|
||||
if (isError($result))
|
||||
return $this->outputJsonError(getError($result));
|
||||
|
||||
$this->outputJsonSuccess(getData($result));
|
||||
$this->outputJsonSuccess(getData($result));
|
||||
} else if(getData($this->StudentModel->isStudent(getAuthUID())) ?? false) { // $isStudent
|
||||
$result = $this->StudiensemesterModel->getWhereStudentHasLvs(getAuthUID());
|
||||
|
||||
if (isError($result))
|
||||
return $this->outputJsonError(getError($result));
|
||||
|
||||
$this->outputJsonSuccess(getData($result));
|
||||
} else {
|
||||
$this->outputJsonError('neither student or mitarbeiter');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,13 +73,27 @@ class Mylv extends Auth_Controller
|
||||
public function Lvs($studiensemester_kurzbz)
|
||||
{
|
||||
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
|
||||
$this->load->model('crm/Student_model', 'StudentModel');
|
||||
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
|
||||
|
||||
$result = $this->LehrveranstaltungModel->getLvsByStudentWithGrades(getAuthUID(), $studiensemester_kurzbz, getUserLanguage());
|
||||
$isMitarbeiter = getData($this->MitarbeiterModel->isMitarbeiter(getAuthUID())) ?? false;
|
||||
if($isMitarbeiter) {
|
||||
$result = $this->LehrveranstaltungModel->getLvsByMitarbeiterInSemester(getAuthUID(), $studiensemester_kurzbz);
|
||||
|
||||
if (isError($result))
|
||||
return $this->outputJsonError(getError($result));
|
||||
if (isError($result))
|
||||
return $this->outputJsonError(getError($result));
|
||||
|
||||
$this->outputJsonSuccess(getData($result));
|
||||
$this->outputJsonSuccess(getData($result));
|
||||
} else if(getData($this->StudentModel->isStudent(getAuthUID())) ?? false) { // $isStudent
|
||||
$result = $this->LehrveranstaltungModel->getLvsByStudentWithGrades(getAuthUID(), $studiensemester_kurzbz, getUserLanguage());
|
||||
|
||||
if (isError($result))
|
||||
return $this->outputJsonError(getError($result));
|
||||
|
||||
$this->outputJsonSuccess(getData($result));
|
||||
} else {
|
||||
$this->outputJsonError('neither student or mitarbeiter');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -215,8 +215,11 @@ class Pruefungsprotokoll extends Auth_Controller
|
||||
if (hasData($abschlusspruefung))
|
||||
{
|
||||
$abschlusspruefung_data = getData($abschlusspruefung);
|
||||
if ($this->permissionlib->isBerechtigt('admin') ||
|
||||
(isset($abschlusspruefung_data->studiengang_kz) && $this->permissionlib->isBerechtigt('assistenz', 'suid', $abschlusspruefung_data->studiengang_kz))
|
||||
if ($this->permissionlib->isBerechtigt('admin')
|
||||
|| (
|
||||
isset($abschlusspruefung_data->studiengang_kz)
|
||||
&& $this->permissionlib->isBerechtigt('assistenz', 'suid', $abschlusspruefung_data->studiengang_kz)
|
||||
)
|
||||
|| $this->_uid === $abschlusspruefung_data->uid_vorsitz)
|
||||
$result = $abschlusspruefung;
|
||||
else
|
||||
|
||||
@@ -114,6 +114,7 @@ class StundenplanLib
|
||||
return $stundenplan_data;
|
||||
$stundenplan_data = getData($stundenplan_data) ?? [];
|
||||
|
||||
$this->_ci->addMeta("stundenplanData", $stundenplan_data);
|
||||
$function_error = $this->expandObjectInformation($stundenplan_data);
|
||||
if ($function_error)
|
||||
return $function_error;
|
||||
@@ -374,6 +375,39 @@ class StundenplanLib
|
||||
$item->gruppe = $gruppe_obj_array;
|
||||
$item->lektor = $lektor_obj_array;
|
||||
|
||||
$this->_ci->load->library('PermissionLib');
|
||||
$berechtigt_begrenzt = $this->_ci->permissionlib->isBerechtigt('lehre/reservierung:begrenzt', 'sui');
|
||||
|
||||
$now = time();
|
||||
$res_lektor_start = $this->jump_day($now, RES_TAGE_LEKTOR_MIN - 1);
|
||||
$res_lektor_ende = mktime(0, 0, 0, date('m', $now), date('d', $now) + RES_TAGE_LEKTOR_BIS, date('Y', $now));
|
||||
|
||||
$start_date = is_numeric($item->beginn) ? $item->beginn : strtotime($item->beginn);
|
||||
if (!date('w', $start_date)) {
|
||||
$start_date = $this->jump_day($start_date, 1);
|
||||
}
|
||||
|
||||
$start_date_str = date('Y-m-d', $start_date);
|
||||
$res_lektor_start_str = date('Y-m-d', $res_lektor_start);
|
||||
$res_lektor_ende_str = date('Y-m-d', $res_lektor_ende);
|
||||
|
||||
$show_delete = (
|
||||
(
|
||||
$berechtigt_begrenzt &&
|
||||
(
|
||||
(isset($item->insertvon) && $item->insertvon == getAuthUID()) ||
|
||||
(isset($item->uids) && in_array(getAuthUID(), $item->uids))
|
||||
)
|
||||
) &&
|
||||
$start_date_str >= $res_lektor_start_str &&
|
||||
$start_date_str <= $res_lektor_ende_str
|
||||
);
|
||||
|
||||
if ($show_delete)
|
||||
$item->deletable = true;
|
||||
else
|
||||
$item->deletable = false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,6 +503,219 @@ class StundenplanLib
|
||||
return success($stundenplan_data);
|
||||
}
|
||||
|
||||
public function addReservation($start, $end, $title, $beschreibung, $ort_kurzbz, $lektoren = null, $studiengang = null, $semester = null, $verband = null, $gruppe = null, $spezialgruppe = null)
|
||||
{
|
||||
$this->_ci =& get_instance();
|
||||
$this->_ci->load->model('ressource/Stunde_model', 'StundeModel');
|
||||
$this->_ci->load->model('ressource/Reservierung_model', 'ReservierungModel');
|
||||
$this->_ci->load->model('ressource/stundenplandev_model', 'StundenplandevModel');
|
||||
$this->_ci->load->model('ressource/stundenplan_model', 'StundenplanModel');
|
||||
$this->_ci->load->library('PermissionLib');
|
||||
|
||||
$startTime = new DateTime($start);
|
||||
$endTime = new DateTime($end);
|
||||
|
||||
$stunden = $this->_ci->StundeModel->loadWhere(array(
|
||||
'beginn <' => $endTime->format('H:i:s'),
|
||||
'ende >' => $startTime->format('H:i:s')
|
||||
));
|
||||
|
||||
if (!hasData($stunden))
|
||||
{
|
||||
return error("Keine Stunden vorhanden");
|
||||
}
|
||||
|
||||
$stunden = array_column(getData($stunden), 'stunde');
|
||||
|
||||
$this->_ci->StundenplandevModel->db->select('1');
|
||||
$this->_ci->StundenplandevModel->db->where('datum', $startTime->format('Y-m-d'));
|
||||
$this->_ci->StundenplandevModel->db->where('ort_kurzbz', $ort_kurzbz);
|
||||
$this->_ci->StundenplandevModel->db->where_in('stunde', $stunden);
|
||||
$stundenplandev_belegung = $this->_ci->StundenplandevModel->load();
|
||||
|
||||
$this->_ci->StundenplanModel->db->select('1');
|
||||
$this->_ci->StundenplanModel->db->where('ort_kurzbz', $ort_kurzbz);
|
||||
$this->_ci->StundenplanModel->db->where('datum', $startTime->format('Y-m-d'));
|
||||
$this->_ci->StundenplanModel->db->where_in('stunde', $stunden);
|
||||
$stundenplan_belegung = $this->_ci->StundenplanModel->load();
|
||||
|
||||
if ((hasData($stundenplandev_belegung) || hasData($stundenplan_belegung))
|
||||
&& !$this->_ci->permissionlib->isBerechtigt('lehre/reservierungAdvanced'))
|
||||
return error ('lvplan/bereitsReserviert');
|
||||
|
||||
$this->_ci->ReservierungModel->addSelect('stunde');
|
||||
$reservation_hours = $this->_ci->ReservierungModel->loadWhere(array('datum' => $startTime->format('Y-m-d'), 'ort_kurzbz' => $ort_kurzbz));
|
||||
|
||||
|
||||
if (isError($reservation_hours))
|
||||
return $reservation_hours;
|
||||
|
||||
$reservation_hours = hasData($reservation_hours) ? array_column(getData($reservation_hours), 'stunde') : array();
|
||||
|
||||
if (!empty(array_intersect($stunden, $reservation_hours))
|
||||
&& !$this->_ci->permissionlib->isBerechtigt('lehre/reservierungAdvanced'))
|
||||
return error("lvplan/bereitsReserviert");
|
||||
|
||||
|
||||
if (!empty($lektoren))
|
||||
{
|
||||
foreach ($lektoren as $lektor)
|
||||
{
|
||||
$insert = array('ort_kurzbz' => $ort_kurzbz,
|
||||
'datum' => $startTime->format('Y-m-d'),
|
||||
'titel' => $title,
|
||||
'studiengang_kz' => is_null($studiengang) ? 0 : $studiengang,
|
||||
'beschreibung' => $beschreibung,
|
||||
'insertvon' => getAuthUID(),
|
||||
'uid' => $lektor,
|
||||
'semester' => is_null($semester) ? null : $semester,
|
||||
'verband' => is_null($verband) ? null : $verband,
|
||||
'gruppe' => is_null($gruppe) ? null : $gruppe,
|
||||
'gruppe_kurzbz' => is_null($spezialgruppe) ? null : $spezialgruppe,
|
||||
);
|
||||
|
||||
foreach ($stunden as $stunde)
|
||||
{
|
||||
$insert['stunde'] = $stunde;
|
||||
$check_insert = $this->_ci->ReservierungModel->insert($insert);
|
||||
if (isError($check_insert))
|
||||
return $check_insert;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ($stunden as $stunde)
|
||||
{
|
||||
$check_insert = $this->_ci->ReservierungModel->insert(array(
|
||||
'ort_kurzbz' => $ort_kurzbz,
|
||||
'uid' => getAuthUID(),
|
||||
'stunde' => $stunde,
|
||||
'datum' => $startTime->format('Y-m-d'),
|
||||
'titel' => $title,
|
||||
'studiengang_kz' => is_null($studiengang) ? 0 : $studiengang,
|
||||
'beschreibung' => $beschreibung,
|
||||
'insertvon' => getAuthUID()
|
||||
));
|
||||
if (isError($check_insert))
|
||||
return $check_insert;
|
||||
}
|
||||
}
|
||||
|
||||
return success("Erfolgreich");
|
||||
}
|
||||
|
||||
public function deleteReservation($reservierung_id)
|
||||
{
|
||||
$this->_ci =& get_instance();
|
||||
$this->_ci->load->model('ressource/Reservierung_model', 'ReservierungModel');
|
||||
$this->_ci->load->model('ressource/Stunde_model', 'StundeModel');
|
||||
$this->_ci->load->library('PermissionLib');
|
||||
|
||||
|
||||
$this->_ci->ReservierungModel->db->where_in('reservierung_id', $reservierung_id);
|
||||
$reservation = $this->_ci->ReservierungModel->load();
|
||||
if (isError($reservation))
|
||||
return $reservation;
|
||||
|
||||
if (!hasData($reservation))
|
||||
return error("Reservierungen nicht gefunden");
|
||||
|
||||
$reservations = getData($reservation);
|
||||
|
||||
$today = new DateTime();
|
||||
foreach ($reservations as $reservierung)
|
||||
{
|
||||
if ($today->format('Y-m-d') > $reservierung->datum)
|
||||
return error("Vergangene Reservierungen können nicht gelöscht werden");
|
||||
|
||||
if (($this->_ci->permissionlib->isBerechtigt('lehre/reservierung:begrenzt')) && ($reservierung->insertvon == getAuthUID() || $reservierung->uid === getAuthUID()))
|
||||
{
|
||||
$delete_result = $this->_ci->ReservierungModel->delete($reservierung->reservierung_id);
|
||||
|
||||
if (isError($delete_result))
|
||||
return $delete_result;
|
||||
}
|
||||
}
|
||||
return success("Erfolgreich");
|
||||
}
|
||||
|
||||
|
||||
public function getReservableMap($ort_kurzbz, $start_date, $end_date)
|
||||
{
|
||||
$this->_ci =& get_instance();
|
||||
$this->_ci->load->model('ressource/Ort_model', 'OrtModel');
|
||||
$this->_ci->load->library('PermissionLib');
|
||||
|
||||
$berechtigt_begrenzt = $this->_ci->permissionlib->isBerechtigt('lehre/reservierung:begrenzt', 'suid');
|
||||
$berechtigt_erweitert = $this->_ci->permissionlib->isBerechtigt('lehre/reservierung', 'suid');
|
||||
|
||||
$ort_data = $this->_ci->OrtModel->load($ort_kurzbz);
|
||||
if (isError($ort_data) || !hasData($ort_data))
|
||||
return [];
|
||||
|
||||
$ort_data = getData($ort_data)[0];
|
||||
|
||||
if (!$ort_data->reservieren)
|
||||
return [];
|
||||
|
||||
if (!$berechtigt_begrenzt && !$berechtigt_erweitert)
|
||||
return [];
|
||||
|
||||
$start_ts = is_numeric($start_date) ? (int)$start_date : strtotime($start_date);
|
||||
$end_ts = is_numeric($end_date) ? (int)$end_date : strtotime($end_date);
|
||||
|
||||
if (!$start_ts || !$end_ts)
|
||||
return [];
|
||||
|
||||
if ($end_ts < $start_ts)
|
||||
{
|
||||
$tmp = $start_ts;
|
||||
$start_ts = $end_ts;
|
||||
$end_ts = $tmp;
|
||||
}
|
||||
|
||||
$now = time();
|
||||
$tage_min = defined('RES_TAGE_LEKTOR_MIN') ? (int)RES_TAGE_LEKTOR_MIN : 0;
|
||||
$tage_bis = defined('RES_TAGE_LEKTOR_BIS') ? (int)RES_TAGE_LEKTOR_BIS : 0;
|
||||
|
||||
$datum_res_lektor_start = $this->jump_day($now, $tage_min - 1);
|
||||
$datum_res_lektor_ende = $this->jump_day($now, $tage_bis);
|
||||
|
||||
$start_ymd_allowed = date('Y-m-d', $datum_res_lektor_start);
|
||||
$end_ymd_allowed = date('Y-m-d', $datum_res_lektor_ende);
|
||||
|
||||
$result = [];
|
||||
|
||||
$current = strtotime(date('Y-m-d', $start_ts) . ' 00:00:00');
|
||||
$end_day = strtotime(date('Y-m-d', $end_ts) . ' 00:00:00');
|
||||
|
||||
while ($current <= $end_day)
|
||||
{
|
||||
$ymd = date('Y-m-d', $current);
|
||||
|
||||
if ((int)date('w', $current) === 0)
|
||||
{
|
||||
$result[$ymd] = false;
|
||||
$current = $this->jump_day($current, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
$result[$ymd] = ($ymd >= $start_ymd_allowed && $ymd <= $end_ymd_allowed) ? true : false;
|
||||
|
||||
$current = $this->jump_day($current, 1);
|
||||
}
|
||||
|
||||
return success($result);
|
||||
}
|
||||
|
||||
private function jump_day($timestamp, $days)
|
||||
{
|
||||
$days = (int)$days;
|
||||
$prefix = ($days >= 0 ? '+' : '');
|
||||
return strtotime($prefix . $days . ' days', $timestamp);
|
||||
}
|
||||
|
||||
// start of the private functions ########################################################################################################
|
||||
|
||||
// function used to sort an array of studiensemester strings
|
||||
|
||||
@@ -11,4 +11,73 @@ class Mobilitaet_model extends DB_Model
|
||||
$this->dbTable = 'bis.tbl_mobilitaet';
|
||||
$this->pk = 'mobilitaet_id';
|
||||
}
|
||||
|
||||
public function getMobilityZusatzForUids($uids) {
|
||||
$qry = "SELECT distinct on(nachname, vorname, public.tbl_benutzer.person_id) uid,
|
||||
tbl_mitarbeiter.mitarbeiter_uid,
|
||||
tbl_note.lkt_ueberschreibbar, tbl_note.anmerkung,
|
||||
tbl_mobilitaet.mobilitaetstyp_kurzbz,
|
||||
(CASE WHEN bis.tbl_mobilitaet.studiensemester_kurzbz = vw_student_lehrveranstaltung.studiensemester_kurzbz THEN 1 ELSE 0 END) as doubledegree,
|
||||
public.tbl_prestudent.gsstudientyp_kurzbz as ddtype,
|
||||
(SELECT status_kurzbz FROM public.tbl_prestudentstatus
|
||||
WHERE prestudent_id=tbl_student.prestudent_id
|
||||
ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1) as studienstatus
|
||||
FROM
|
||||
campus.vw_student_lehrveranstaltung
|
||||
JOIN public.tbl_benutzer USING(uid)
|
||||
JOIN public.tbl_person USING(person_id)
|
||||
LEFT JOIN public.tbl_student ON(uid=student_uid)
|
||||
LEFT JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid)
|
||||
LEFT JOIN public.tbl_studentlehrverband USING(student_uid,studiensemester_kurzbz)
|
||||
LEFT JOIN lehre.tbl_zeugnisnote on(vw_student_lehrveranstaltung.lehrveranstaltung_id=tbl_zeugnisnote.lehrveranstaltung_id
|
||||
AND tbl_zeugnisnote.student_uid=tbl_student.student_uid
|
||||
AND tbl_zeugnisnote.studiensemester_kurzbz=tbl_studentlehrverband.studiensemester_kurzbz)
|
||||
LEFT JOIN lehre.tbl_note USING (note)
|
||||
LEFT JOIN bis.tbl_bisio ON(uid=tbl_bisio.student_uid)
|
||||
LEFT JOIN public.tbl_studiengang ON(tbl_student.studiengang_kz=tbl_studiengang.studiengang_kz)
|
||||
LEFT JOIN bis.tbl_mobilitaet USING(prestudent_id)
|
||||
LEFT JOIN public.tbl_prestudent USING(prestudent_id)
|
||||
WHERE uid IN ?";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, [$uids]);
|
||||
}
|
||||
|
||||
public function formatZusatz($entry, $erhalter_kz) {
|
||||
$zusatz = '';
|
||||
|
||||
if (isset($entry->studienstatus) && $entry->studienstatus === 'Incoming') {
|
||||
$zusatz = '(i)';
|
||||
}
|
||||
|
||||
if (isset($entry->lkt_ueberschreibbar) && $entry->lkt_ueberschreibbar === false) {
|
||||
$zusatz .= ' (' . ($entry->anmerkung ?? '') . ')';
|
||||
}
|
||||
|
||||
if (isset($entry->mitarbeiter_uid) && $entry->mitarbeiter_uid !== null) {
|
||||
$zusatz .= ' (ma)';
|
||||
}
|
||||
|
||||
if (isset($entry->stg_kz_student) && $entry->stg_kz_student == $erhalter_kz) {
|
||||
$zusatz .= ' (a.o.)';
|
||||
}
|
||||
|
||||
if (
|
||||
isset($entry->mobilitaetstyp_kurzbz) && $entry->mobilitaetstyp_kurzbz &&
|
||||
isset($entry->doubledegree) && $entry->doubledegree === 1
|
||||
) {
|
||||
$zusatz .= ' (d.d.';
|
||||
|
||||
$ddtype = $entry->ddtype ?? null;
|
||||
|
||||
if ($ddtype == 'Intern') {
|
||||
$zusatz .= 'i.)';
|
||||
} elseif ($ddtype == 'Extern') {
|
||||
$zusatz .= 'o.)';
|
||||
} else {
|
||||
$zusatz .= ')';
|
||||
}
|
||||
}
|
||||
|
||||
return $zusatz;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,12 +100,14 @@ class Abschlusspruefung_model extends DB_Model
|
||||
|
||||
if (isError($abschlussarbeit))
|
||||
return $abschlussarbeit;
|
||||
|
||||
if (hasData($abschlussarbeit))
|
||||
{
|
||||
$abschlussarbeit = getData($abschlussarbeit)[0];
|
||||
$abschlusspruefungdata->projektarbeit_studiengangstyp_name = $abschlussarbeit->projekttyp_kurzbz;
|
||||
$abschlusspruefungdata->abschlussarbeit_titel = $abschlussarbeit->titel;
|
||||
$abschlusspruefungdata->abschlussarbeit_note = $abschlussarbeit->note;
|
||||
$abschlusspruefungdata->abschlussarbeit_sprache = $abschlussarbeit->sprache_bezeichnung;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,4 +52,53 @@ class LePruefung_model extends DB_Model
|
||||
'student_uid' => $student_uid
|
||||
]);
|
||||
}
|
||||
|
||||
public function getPruefungenByLvStudiensemester($lv_id, $sem_kurzbz) {
|
||||
$qry = "SELECT lehre.tbl_pruefung.*, tbl_lehrveranstaltung.bezeichnung as lehrveranstaltung_bezeichnung, tbl_lehrveranstaltung.lehrveranstaltung_id,
|
||||
tbl_note.bezeichnung as note_bezeichnung, tbl_pruefungstyp.beschreibung as typ_beschreibung, tbl_lehreinheit.studiensemester_kurzbz as studiensemester_kurzbz
|
||||
FROM lehre.tbl_pruefung, lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, lehre.tbl_note, lehre.tbl_pruefungstyp
|
||||
WHERE lehre.tbl_pruefung.lehreinheit_id=tbl_lehreinheit.lehreinheit_id
|
||||
AND tbl_lehreinheit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id
|
||||
AND lehre.tbl_pruefung.note = tbl_note.note
|
||||
AND lehre.tbl_pruefung.pruefungstyp_kurzbz=tbl_pruefungstyp.pruefungstyp_kurzbz
|
||||
AND tbl_lehrveranstaltung.lehrveranstaltung_id = ?
|
||||
AND tbl_lehreinheit.studiensemester_kurzbz = ?
|
||||
ORDER BY datum DESC;";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, array($lv_id, $sem_kurzbz));
|
||||
}
|
||||
|
||||
public function getPruefungenByUidTypLvStudiensemester($uid, $typ = null, $lv_id = null, $sem_kurzbz = null) {
|
||||
$params = [$uid];
|
||||
$qry = "SELECT tbl_pruefung.*, tbl_lehrveranstaltung.bezeichnung as lehrveranstaltung_bezeichnung, tbl_lehrveranstaltung.lehrveranstaltung_id,
|
||||
tbl_note.bezeichnung as note_bezeichnung, tbl_pruefungstyp.beschreibung as typ_beschreibung, tbl_lehreinheit.studiensemester_kurzbz as studiensemester_kurzbz
|
||||
FROM lehre.tbl_pruefung, lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, lehre.tbl_note, lehre.tbl_pruefungstyp
|
||||
WHERE student_uid= ?
|
||||
AND tbl_pruefung.lehreinheit_id=tbl_lehreinheit.lehreinheit_id
|
||||
AND tbl_lehreinheit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id
|
||||
AND tbl_pruefung.note = tbl_note.note
|
||||
AND tbl_pruefung.pruefungstyp_kurzbz=tbl_pruefungstyp.pruefungstyp_kurzbz";
|
||||
if ($typ != null)
|
||||
{
|
||||
$qry .= " AND tbl_pruefungstyp.pruefungstyp_kurzbz = ?";
|
||||
$params[] = $typ;
|
||||
}
|
||||
|
||||
if ($lv_id != null)
|
||||
{
|
||||
$qry .= " AND tbl_lehrveranstaltung.lehrveranstaltung_id = ?";
|
||||
$params[] = $lv_id;
|
||||
}
|
||||
|
||||
if ($sem_kurzbz != null)
|
||||
{
|
||||
$qry .= " AND tbl_lehreinheit.studiensemester_kurzbz = ?";
|
||||
$params[] = $sem_kurzbz;
|
||||
}
|
||||
|
||||
|
||||
$qry .= " ORDER BY datum DESC";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, $params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -739,4 +739,26 @@ EOSQL;
|
||||
)";
|
||||
}
|
||||
|
||||
|
||||
public function getAllLehreinheitenForLvaAndMaUid($lva_id, $ma_uid, $sem_kurzbz)
|
||||
{
|
||||
$query = "SELECT DISTINCT tbl_lehreinheitmitarbeiter.lehreinheit_id, tbl_lehreinheit.lehrveranstaltung_id, tbl_lehreinheit.lehrform_kurzbz,
|
||||
tbl_lehreinheitmitarbeiter.mitarbeiter_uid,
|
||||
tbl_lehreinheitgruppe.semester,
|
||||
tbl_lehreinheitgruppe.verband,
|
||||
tbl_lehreinheitgruppe.gruppe,
|
||||
tbl_lehreinheitgruppe.gruppe_kurzbz,
|
||||
tbl_lehrveranstaltung.kurzbz,
|
||||
tbl_studiengang.kurzbzlang,
|
||||
(SELECT COUNT(DISTINCT datum) FROM campus.vw_stundenplan WHERE lehreinheit_id = lehre.tbl_lehreinheit.lehreinheit_id) as termincount,
|
||||
(SELECT COUNT(*) FROM campus.vw_student_lehrveranstaltung WHERE lehreinheit_id = lehre.tbl_lehreinheit.lehreinheit_id) as studentcount
|
||||
FROM lehre.tbl_lehreinheit JOIN lehre.tbl_lehreinheitmitarbeiter USING(lehreinheit_id)
|
||||
JOIN lehre.tbl_lehreinheitgruppe USING(lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
JOIN public.tbl_studiengang ON (tbl_lehreinheitgruppe.studiengang_kz = tbl_studiengang.studiengang_kz)
|
||||
WHERE lehrveranstaltung_id = ? AND studiensemester_kurzbz = ? AND mitarbeiter_uid = ?
|
||||
ORDER BY tbl_lehreinheitgruppe.gruppe_kurzbz";
|
||||
|
||||
return $this->execQuery($query, [$lva_id, $sem_kurzbz, $ma_uid]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,7 +317,7 @@ class Lehrveranstaltung_model extends DB_Model
|
||||
tbl_bisio.bisio_id, tbl_bisio.von, tbl_bisio.bis, tbl_student.studiengang_kz AS stg_kz_student,
|
||||
tbl_zeugnisnote.note, tbl_mitarbeiter.mitarbeiter_uid, tbl_person.matr_nr, tbl_benutzer.uid,
|
||||
UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel, tbl_studiengang.orgform_kurzbz, vw_student_lehrveranstaltung.semester, vw_student_lehrveranstaltung.studiensemester_kurzbz, vw_student_lehrveranstaltung.bezeichnung,
|
||||
tbl_student.prestudent_id
|
||||
tbl_student.prestudent_id, campus.vw_student_lehrveranstaltung.lehreinheit_id
|
||||
FROM
|
||||
campus.vw_student_lehrveranstaltung
|
||||
JOIN public.tbl_benutzer USING(uid)
|
||||
@@ -1346,4 +1346,65 @@ class Lehrveranstaltung_model extends DB_Model
|
||||
|
||||
return $this->execQuery($qry, $params);
|
||||
}
|
||||
|
||||
public function getLvForLektorInSemester($sem_kurzbz, $uid) {
|
||||
$qry = "SELECT DISTINCT (tbl_lehrveranstaltung.lehrveranstaltung_id),
|
||||
UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as stg_kurzbz,
|
||||
tbl_lehrveranstaltung.semester as lv_semester,
|
||||
tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung,
|
||||
(SELECT kurzbz FROM public.tbl_mitarbeiter
|
||||
WHERE mitarbeiter_uid=tbl_lehreinheitmitarbeiter.mitarbeiter_uid) as lektor
|
||||
FROM
|
||||
lehre.tbl_lehreinheit JOIN lehre.tbl_lehreinheitmitarbeiter USING(lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
JOIN public.tbl_studiengang USING(studiengang_kz)
|
||||
JOIN lehre.tbl_lehrveranstaltung as lehrfach ON(tbl_lehreinheit.lehrfach_id=lehrfach.lehrveranstaltung_id)
|
||||
WHERE
|
||||
tbl_lehreinheit.studiensemester_kurzbz = ?
|
||||
AND mitarbeiter_uid = ?
|
||||
ORDER BY stg_kurzbz,lv_semester,lv_bezeichnung";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, array($sem_kurzbz, $uid));
|
||||
}
|
||||
|
||||
// used for cis4 mylv mitarbeiter
|
||||
public function getLvsByMitarbeiterInSemester($mitarbeiter_uid, $sem_kurzbz) {
|
||||
$qry = "SELECT * FROM (
|
||||
SELECT DISTINCT ON (lehre.tbl_lehrveranstaltung.lehrveranstaltung_id)
|
||||
public.tbl_studiengang.studiengang_kz,
|
||||
lehre.tbl_lehrveranstaltung.semester,
|
||||
public.tbl_studiengang.bezeichnung as sg_bezeichnung,
|
||||
public.tbl_studiengang.english as sg_bezeichnung_eng,
|
||||
UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as studiengang_kuerzel,
|
||||
lehre.tbl_lehrveranstaltung.lehrveranstaltung_id,
|
||||
lehre.tbl_lehrveranstaltung.bezeichnung,
|
||||
lehre.tbl_lehrveranstaltung.bezeichnung_english as bezeichnung_eng,
|
||||
lehre.tbl_lehrveranstaltung.farbe,
|
||||
lehre.tbl_lehrveranstaltung.lvinfo,
|
||||
lehre.tbl_lehrveranstaltung.benotung,
|
||||
lehre.tbl_lehrveranstaltung.orgform_kurzbz,
|
||||
lehre.tbl_lehrveranstaltung.sprache,
|
||||
lehre.tbl_lehrveranstaltung.ects,
|
||||
lehre.tbl_lehrveranstaltung.incoming
|
||||
FROM
|
||||
lehre.tbl_lehreinheit JOIN lehre.tbl_lehreinheitmitarbeiter USING(lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
JOIN public.tbl_studiengang USING(studiengang_kz)
|
||||
JOIN lehre.tbl_lehrveranstaltung as lehrfach ON(tbl_lehreinheit.lehrfach_id=lehrfach.lehrveranstaltung_id)
|
||||
WHERE
|
||||
tbl_lehreinheit.studiensemester_kurzbz = ?
|
||||
AND mitarbeiter_uid = ?) as distincted_by_lva_id
|
||||
JOIN (
|
||||
SELECT lehrveranstaltung_id, TRUNC(SUM(lehre.tbl_lehreinheitmitarbeiter.semesterstunden)) as semesterstunden
|
||||
FROM lehre.tbl_lehreinheit
|
||||
JOIN lehre.tbl_lehreinheitmitarbeiter USING(lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
WHERE tbl_lehreinheit.studiensemester_kurzbz = ?
|
||||
AND mitarbeiter_uid = ?
|
||||
GROUP BY lehrveranstaltung_id
|
||||
) semesterstundenAggregatedSubquery USING(lehrveranstaltung_id)
|
||||
ORDER BY studiengang_kuerzel, semester, bezeichnung";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, [$sem_kurzbz, $mitarbeiter_uid, $sem_kurzbz, $mitarbeiter_uid]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ class Lvgesamtnote_model extends DB_Model
|
||||
}
|
||||
|
||||
/**
|
||||
* Laedt die Noten
|
||||
* Laedt die Noten - lvgesamtnote (Vorschlag) JOIN tbl.note (zeugnisnote)
|
||||
*
|
||||
* @param integer $lehrveranstaltung_id
|
||||
* @param string $student_uid
|
||||
@@ -46,4 +46,19 @@ class Lvgesamtnote_model extends DB_Model
|
||||
|
||||
return $this->loadWhere($where);
|
||||
}
|
||||
|
||||
public function getLvGesamtNoteVorschlag($lehrveranstaltung_id, $student_uid, $studiensemester_kurzbz)
|
||||
{
|
||||
$qry = "SELECT * FROM campus.tbl_lvgesamtnote
|
||||
WHERE campus.tbl_lvgesamtnote.student_uid = ?
|
||||
AND campus.tbl_lvgesamtnote.studiensemester_kurzbz = ?";
|
||||
$params = [$student_uid, $studiensemester_kurzbz];
|
||||
|
||||
if ($lehrveranstaltung_id) {
|
||||
$qry .= "AND campus.tbl_lvgesamtnote.lehrveranstaltung_id = ?";
|
||||
$params[] = $lehrveranstaltung_id;
|
||||
}
|
||||
|
||||
return $this->execReadOnlyQuery($qry, $params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,33 @@ class Note_model extends DB_Model
|
||||
$this->dbTable = 'lehre.tbl_note';
|
||||
$this->pk = 'note';
|
||||
}
|
||||
|
||||
|
||||
public function getAllActive() {
|
||||
$qry ="SELECT *
|
||||
FROM lehre.tbl_note
|
||||
WHERE aktiv = true";
|
||||
|
||||
return $this->execReadOnlyQuery($qry);
|
||||
}
|
||||
|
||||
// used to determine the primary key of note "entschuldigt" to avoid hardcoded magic numbers
|
||||
// that might differ in a different installation of fhcomplete
|
||||
public function getEntschuldigtNote() {
|
||||
$qry ="SELECT *
|
||||
FROM lehre.tbl_note
|
||||
WHERE bezeichnung = 'entschuldigt'";
|
||||
|
||||
return $this->execReadOnlyQuery($qry);
|
||||
}
|
||||
|
||||
// used to determine the primary key of note "noch nicht eingetragen" to avoid hardcoded magic numbers
|
||||
// that might differ in a different installation of fhcomplete
|
||||
public function getNochNichtEingetragenNote() {
|
||||
$qry ="SELECT *
|
||||
FROM lehre.tbl_note
|
||||
WHERE bezeichnung = 'Noch nicht eingetragen'";
|
||||
|
||||
return $this->execReadOnlyQuery($qry);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,9 @@ class Notenschluesselaufteilung_model extends DB_Model
|
||||
$this->load->model('education/Notenschluesselzuordnung_model', 'NotenschluesselzuordnungModel');
|
||||
$notenschluessel_kurzbz = $this->NotenschluesselzuordnungModel->getKurzbzForLv($lehrveranstaltung_id, $studiensemester_kurzbz);
|
||||
|
||||
if($notenschluessel_kurzbz == null)
|
||||
return success(null);
|
||||
|
||||
$this->addSelect("note");
|
||||
$this->addOrder("punkte", "DESC");
|
||||
$this->addLimit(1);
|
||||
|
||||
@@ -61,6 +61,174 @@ class Paabgabe_model extends DB_Model
|
||||
return $this->execReadOnlyQuery($qry, array($person_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets project submissions for search criteria.
|
||||
* @param array $projekttyp_kurzbz_arr contains all relevant project types (e.g. Bachelor)
|
||||
* @param int $studiengang_kz study program
|
||||
* @param string $abgabetyp_kurzbz project submission type (e.g. end upload, intermediate submission)
|
||||
* @param string $abgabedatum due date for hand-in
|
||||
* @param string $personSearchString for searching by person, i.e. name, uid, person/prestudent id
|
||||
* @param int $limit limiting max number of results if search criteria is not precise enough
|
||||
* @return object
|
||||
*/
|
||||
public function getPaAbgaben(
|
||||
$projekttyp_kurzbz_arr,
|
||||
$studiengang_kz = null,
|
||||
$abgabetyp_kurzbz = null,
|
||||
$abgabedatum = null,
|
||||
$personSearchString = null,
|
||||
$limit = 1000
|
||||
) {
|
||||
$params = [];
|
||||
|
||||
$qry = "
|
||||
SELECT
|
||||
stg.bezeichnung AS stgbez, paabg.datum AS termin,
|
||||
paabg.paabgabe_id, paabg.projektarbeit_id, paabg.paabgabetyp_kurzbz, paabg.abgabedatum,
|
||||
abgabetyp.bezeichnung AS paabgabetyp_bezeichnung, ben.uid, pers.vorname, pers.nachname, pa.projekttyp_kurzbz, pa.titel,
|
||||
UPPER(stg.typ || stg.kurzbz) AS studiengang_kuerzel,
|
||||
(
|
||||
/* show all relevant Studiengänge of person and wether it is an employee*/
|
||||
SELECT
|
||||
STRING_AGG(studiengang || ' ' || last_status, ' | ')
|
||||
|| (CASE WHEN EXISTS (
|
||||
SELECT 1 FROM public.tbl_mitarbeiter ma
|
||||
JOIN public.tbl_benutzer ben ON ma.mitarbeiter_uid = ben.uid
|
||||
WHERE person_id = prestudents.person_id
|
||||
AND ben.aktiv
|
||||
) THEN ' | Mitarbeiter' ELSE '' END)
|
||||
FROM (
|
||||
SELECT
|
||||
DISTINCT person_id, prestudent_id, UPPER(stg.typ || stg.kurzbz) AS studiengang,
|
||||
get_rolle_prestudent(ps.prestudent_id, null) AS last_status
|
||||
FROM
|
||||
public.tbl_prestudent ps
|
||||
JOIN public.tbl_studiengang stg USING (studiengang_kz)
|
||||
WHERE
|
||||
person_id = pers.person_id
|
||||
ORDER BY
|
||||
prestudent_id DESC
|
||||
) prestudents
|
||||
WHERE
|
||||
last_status IN ('Abgewiesener','Aufgenommener', 'Student', 'Incoming', 'Diplomand', 'Abbrecher', 'Unterbrecher', 'Absolvent')
|
||||
GROUP BY
|
||||
person_id
|
||||
LIMIT 1;
|
||||
) AS status
|
||||
FROM
|
||||
lehre.tbl_projektarbeit pa
|
||||
JOIN campus.tbl_paabgabe paabg USING(projektarbeit_id)
|
||||
JOIN campus.tbl_paabgabetyp abgabetyp USING(paabgabetyp_kurzbz)
|
||||
LEFT JOIN public.tbl_benutzer ben ON(uid=student_uid)
|
||||
LEFT JOIN public.tbl_person pers ON(ben.person_id=pers.person_id)
|
||||
LEFT JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
LEFT JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
LEFT JOIN public.tbl_studiengang stg USING(studiengang_kz)
|
||||
WHERE
|
||||
TRUE";
|
||||
|
||||
if (isset($projekttyp_kurzbz_arr) && !isEmptyArray($projekttyp_kurzbz_arr))
|
||||
{
|
||||
$qry .= " AND projekttyp_kurzbz IN ?";
|
||||
$params[] = $projekttyp_kurzbz_arr;
|
||||
}
|
||||
|
||||
if (isset($studiengang_kz) && is_numeric($studiengang_kz))
|
||||
{
|
||||
$qry .= " AND stg.studiengang_kz=?";
|
||||
$params[] = $studiengang_kz;
|
||||
}
|
||||
|
||||
if (isset($abgabetyp_kurzbz))
|
||||
{
|
||||
$qry .= " AND paabg.paabgabetyp_kurzbz=?";
|
||||
$params[] = $abgabetyp_kurzbz;
|
||||
}
|
||||
|
||||
if (isset($abgabedatum))
|
||||
{
|
||||
$qry .= " AND paabg.datum=?";
|
||||
$params[] = $abgabedatum;
|
||||
}
|
||||
|
||||
if (is_numeric($personSearchString))
|
||||
{
|
||||
$personSearchString = (int) $personSearchString;
|
||||
$params = array_merge($params, [$personSearchString, $personSearchString]);
|
||||
$qry .= " AND (
|
||||
pers.person_id = ?
|
||||
OR EXISTS (SELECT 1 FROM public.tbl_prestudent WHERE person_id = pers.person_id AND prestudent_id = ?)
|
||||
)";
|
||||
}
|
||||
elseif (is_string($personSearchString))
|
||||
{
|
||||
// remove empty spaces and lowercase
|
||||
$personSearchString = strtolower(str_replace(' ', '', $personSearchString));
|
||||
$qry .= " AND (
|
||||
LOWER(REPLACE(pers.nachname || pers.vorname || pers.nachname, ' ', '')) LIKE ".$this->db->escape('%'.$personSearchString.'%')."
|
||||
OR ben.uid LIKE ".$this->db->escape('%'.$personSearchString.'%')."
|
||||
)";
|
||||
}
|
||||
|
||||
$qry .= " ORDER BY nachname";
|
||||
|
||||
if (isset($limit) && is_numeric($limit) && (!isset($studiengang_kz) || !is_numeric($studiengang_kz)) && !isset($abgabedatum))
|
||||
{
|
||||
$qry .= " LIMIT ?";
|
||||
$params[] = $limit;
|
||||
}
|
||||
|
||||
return $this->execReadOnlyQuery($qry, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets due dates for projekt submission search criteria.
|
||||
* @param array $projekttyp_kurzbz_arr contains all relevant project types (e.g. Bachelor)
|
||||
* @param int $studiengang_kz study program
|
||||
* @param string $abgabetyp_kurzbz project submission type (e.g. end upload, intermediate submission)
|
||||
* @return object
|
||||
*/
|
||||
public function getTermine($projekttyp_kurzbz_arr, $studiengang_kz, $abgabetyp_kurzbz)
|
||||
{
|
||||
$params = [];
|
||||
|
||||
$qry = "
|
||||
SELECT
|
||||
DISTINCT tbl_paabgabe.datum as termin, to_char(tbl_paabgabe.datum, 'DD.MM.YYYY') as termin_anzeige
|
||||
FROM
|
||||
lehre.tbl_projektarbeit
|
||||
JOIN campus.tbl_paabgabe USING(projektarbeit_id)
|
||||
LEFT JOIN public.tbl_benutzer ON(uid=student_uid)
|
||||
LEFT JOIN public.tbl_person ON(tbl_benutzer.person_id=tbl_person.person_id)
|
||||
LEFT JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
LEFT JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
LEFT JOIN public.tbl_studiengang USING(studiengang_kz)
|
||||
WHERE
|
||||
TRUE";
|
||||
|
||||
if (isset($projekttyp_kurzbz_arr) && !isEmptyArray($projekttyp_kurzbz_arr))
|
||||
{
|
||||
$qry .= " AND projekttyp_kurzbz IN ?";
|
||||
$params[] = $projekttyp_kurzbz_arr;
|
||||
}
|
||||
|
||||
if (isset($studiengang_kz) && is_numeric($studiengang_kz))
|
||||
{
|
||||
$qry .= " AND public.tbl_studiengang.studiengang_kz=?";
|
||||
$params[] = $studiengang_kz;
|
||||
}
|
||||
|
||||
if (isset($abgabetyp_kurzbz))
|
||||
{
|
||||
$qry .= " AND campus.tbl_paabgabe.paabgabetyp_kurzbz=?";
|
||||
$params[] = $abgabetyp_kurzbz;
|
||||
}
|
||||
|
||||
$qry .= " ORDER BY termin DESC";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, $params);
|
||||
}
|
||||
|
||||
public function findAbgabenNewOrUpdatedSince($interval, $relevantTypes)
|
||||
{
|
||||
|
||||
|
||||
@@ -23,9 +23,11 @@ class Projektarbeit_model extends DB_Model
|
||||
*/
|
||||
public function getProjektarbeit($student_uid, $studiengang_kz = null, $studiensemester_kurzbz = null, $projekttyp = null, $final = null)
|
||||
{
|
||||
$sprache_index = "COALESCE((SELECT index FROM public.tbl_sprache WHERE sprache=" . $this->escape(getUserLanguage()) . " LIMIT 1), 1)";
|
||||
$qry = "SELECT
|
||||
pa.*, tbl_projekttyp.bezeichnung,
|
||||
tbl_lehreinheit.studiensemester_kurzbz, tbl_lehrveranstaltung.lehrveranstaltung_id,
|
||||
tbl_sprache.bezeichnung[".$sprache_index."] AS sprache_bezeichnung,
|
||||
tbl_firma.name AS firma_name,
|
||||
(
|
||||
SELECT
|
||||
@@ -44,6 +46,7 @@ class Projektarbeit_model extends DB_Model
|
||||
JOIN lehre.tbl_lehreinheit USING (lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id)
|
||||
LEFT JOIN public.tbl_firma USING (firma_id)
|
||||
LEFT JOIN public.tbl_sprache ON pa.sprache = tbl_sprache.sprache
|
||||
WHERE
|
||||
pa.student_uid = ?";
|
||||
|
||||
|
||||
@@ -306,4 +306,5 @@ class Pruefung_model extends DB_Model
|
||||
|
||||
return $this->loadWhereCommitteeExamsFailed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,6 +59,37 @@ class Studienplan_model extends DB_Model
|
||||
'tbl_studienplan_lehrveranstaltung.semester' => $semester
|
||||
));
|
||||
}
|
||||
|
||||
public function getStudienplanByLvaSemKurzbz($lehrveranstaltung_id, $studiensemester_kurzbz) {
|
||||
$qry= "
|
||||
SELECT
|
||||
DISTINCT tbl_studienplan.*
|
||||
FROM
|
||||
lehre.tbl_studienplan
|
||||
JOIN lehre.tbl_studienplan_lehrveranstaltung
|
||||
USING(studienplan_id)
|
||||
WHERE
|
||||
tbl_studienplan_lehrveranstaltung.lehrveranstaltung_id IN (
|
||||
SELECT
|
||||
lv.lehrveranstaltung_id
|
||||
FROM
|
||||
lehre.tbl_lehrveranstaltung AS lv
|
||||
LEFT JOIN lehre.tbl_lehrveranstaltung AS t ON t.lehrveranstaltung_id=lv.lehrveranstaltung_template_id
|
||||
WHERE
|
||||
lv.lehrtyp_kurzbz<>'tpl'
|
||||
AND (lv.lehrveranstaltung_id= ? OR (lv.lehrveranstaltung_template_id= ? AND t.lehrtyp_kurzbz='tpl'))
|
||||
)
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM
|
||||
lehre.tbl_studienplan_semester
|
||||
WHERE studienplan_id=tbl_studienplan.studienplan_id
|
||||
AND studiensemester_kurzbz= ?
|
||||
AND semester = tbl_studienplan_lehrveranstaltung.semester)
|
||||
ORDER BY bezeichnung";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, array($lehrveranstaltung_id, $lehrveranstaltung_id, $studiensemester_kurzbz));
|
||||
}
|
||||
|
||||
public function getStudienplanLehrveranstaltungForPrestudent($studienplan_id, $semester, $prestudent_id)
|
||||
{
|
||||
|
||||
@@ -242,6 +242,30 @@ class Studiensemester_model extends DB_Model
|
||||
return $this->loadWhere(['uid' => $student_uid, 'v.lehre' => true]);
|
||||
}
|
||||
|
||||
public function getWhereMitarbeiterHasLvs($uid) {
|
||||
// first order by year with last 2 letter from right,
|
||||
// then order by WS/SS inside the years
|
||||
// query it asc so the ordering magic in cis4 turns it around again
|
||||
$qry = "WITH unique_semesters AS (
|
||||
SELECT DISTINCT ON (studiensemester_kurzbz)
|
||||
studiensemester_kurzbz,
|
||||
start,
|
||||
ende,
|
||||
bezeichnung,
|
||||
studienjahr_kurzbz
|
||||
FROM lehre.tbl_lehreinheit
|
||||
JOIN lehre.tbl_lehreinheitmitarbeiter USING(lehreinheit_id)
|
||||
JOIN public.tbl_studiensemester USING(studiensemester_kurzbz)
|
||||
WHERE mitarbeiter_uid = ?
|
||||
)
|
||||
SELECT * FROM unique_semesters
|
||||
ORDER BY
|
||||
RIGHT(studiensemester_kurzbz, 2) ASC,
|
||||
LEFT(studiensemester_kurzbz, 2) ASC;";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, [$uid]);
|
||||
}
|
||||
|
||||
public function getAktAndFutureSemester()
|
||||
{
|
||||
$query = 'SELECT studiensemester_kurzbz
|
||||
|
||||
@@ -50,11 +50,12 @@ class Reservierung_model extends DB_Model
|
||||
|
||||
$query_result = $this->execReadOnlyQuery("
|
||||
SELECT
|
||||
'reservierung' as type, beginn, ende, datum,
|
||||
DISTINCT(insertvon),
|
||||
'reservierung' as type, beginn, ende, datum, array_agg(DISTINCT reservierung_id) AS reservierung_id,
|
||||
COALESCE(titel, beschreibung) as topic,
|
||||
array_agg(DISTINCT mitarbeiter_kurzbz) as lektor,
|
||||
array_agg(DISTINCT (gruppe,verband,semester,studiengang_kz,gruppen_kuerzel)) as gruppe,
|
||||
|
||||
array_agg(DISTINCT(uid)) as uids,
|
||||
ort_kurzbz, 'FFFFFF' as farbe
|
||||
|
||||
FROM
|
||||
@@ -62,7 +63,7 @@ class Reservierung_model extends DB_Model
|
||||
" . $subquery . "
|
||||
) AS subquery
|
||||
|
||||
GROUP BY datum, beginn, ende, ort_kurzbz, titel, beschreibung
|
||||
GROUP BY datum, beginn, ende, ort_kurzbz, titel, beschreibung, insertvon
|
||||
|
||||
ORDER BY datum, beginn
|
||||
", is_null($ort_kurzbz) ? [$uid ?? getAuthUID(), $uid ?? getAuthUID(), $start_date, $end_date] : [$ort_kurzbz, $start_date, $end_date]);
|
||||
@@ -94,11 +95,12 @@ class Reservierung_model extends DB_Model
|
||||
|
||||
$query_result = $this->execReadOnlyQuery("
|
||||
SELECT
|
||||
DISTINCT(insertvon),
|
||||
'reservierung' as type, beginn, ende, datum,
|
||||
COALESCE(titel, beschreibung) as topic,
|
||||
array_agg(DISTINCT mitarbeiter_kurzbz) as lektor,
|
||||
array_agg(DISTINCT (gruppe,verband,semester,studiengang_kz,gruppen_kuerzel)) as gruppe,
|
||||
|
||||
array_agg(DISTINCT(uid)) as uids,
|
||||
ort_kurzbz, 'FFFFFF' as farbe
|
||||
|
||||
FROM
|
||||
@@ -106,7 +108,7 @@ class Reservierung_model extends DB_Model
|
||||
" . $subquery . "
|
||||
) AS subquery
|
||||
|
||||
GROUP BY datum, beginn, ende, ort_kurzbz, titel, beschreibung
|
||||
GROUP BY datum, beginn, ende, ort_kurzbz, titel, beschreibung, insertvon
|
||||
|
||||
ORDER BY datum, beginn
|
||||
", [$uid ?? getAuthUID(), $start_date, $end_date]);
|
||||
|
||||
@@ -12,6 +12,8 @@ class Zeitsperre_model extends DB_Model
|
||||
$this->pk = 'zeitsperre_id';
|
||||
}
|
||||
|
||||
const BLOCKIERENDE_ZEITSPERREN = ['Krank','Urlaub','ZA','DienstV','PflegeU','DienstF','CovidSB','CovidKS'];
|
||||
|
||||
/**
|
||||
* Save or update Zeitsperre.
|
||||
*
|
||||
@@ -61,4 +63,128 @@ class Zeitsperre_model extends DB_Model
|
||||
|
||||
return $this->execQuery($qry);
|
||||
}
|
||||
|
||||
/**
|
||||
* get Zeitsperren of a user
|
||||
*
|
||||
* @param $uid mitarbeiteruid
|
||||
* @param $bisgrenze @true show only entries of actual business year (1.9.- 31.8.)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getZeitsperrenUser($uid, $bisgrenze = true)
|
||||
{
|
||||
$qry = "
|
||||
SELECT
|
||||
tbl_zeitsperre.*, tbl_zeitsperretyp.*, tbl_erreichbarkeit.farbe AS erreichbarkeit_farbe,
|
||||
tbl_erreichbarkeit.beschreibung AS erreichbarkeit_beschreibung,
|
||||
CONCAT (ps.vorname, ' ', ps.nachname) as vertretung
|
||||
FROM (campus.tbl_zeitsperre JOIN campus.tbl_zeitsperretyp USING (zeitsperretyp_kurzbz))
|
||||
LEFT JOIN campus.tbl_erreichbarkeit USING (erreichbarkeit_kurzbz)
|
||||
LEFT JOIN public.tbl_benutzer ON campus.tbl_zeitsperre.vertretung_uid = public.tbl_benutzer.uid
|
||||
LEFT JOIN public.tbl_person ps USING (person_id)
|
||||
WHERE mitarbeiter_uid= ?
|
||||
";
|
||||
|
||||
if($bisgrenze)
|
||||
{
|
||||
$qry.="
|
||||
AND (
|
||||
(date_part('month',vondatum)>=9 AND date_part('year', vondatum)>='".(date('Y')-1)."')
|
||||
OR
|
||||
(date_part('month',vondatum)<9 AND date_part('year', vondatum)>='".(date('Y'))."')
|
||||
)";
|
||||
}
|
||||
|
||||
$qry.= " ORDER BY vondatum DESC";
|
||||
|
||||
return $this->execQuery($qry, array('mitarbeiter_uid' => $uid));
|
||||
}
|
||||
|
||||
/**
|
||||
* check a date for existing zeitsperre
|
||||
*
|
||||
* @param $uid mitarbeiteruid
|
||||
* @param $datum datum to check
|
||||
* @param $stunde stunde (default = null)
|
||||
* @param bool $nurblockierend if only hr relevante zeitsperren have to be checked
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSperreByDate($uid, $datum, $stunde = null, $nurblockierend = false)
|
||||
{
|
||||
$parametersArray = [$datum, $datum];
|
||||
|
||||
$qry = "
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
campus.tbl_zeitsperre
|
||||
WHERE
|
||||
vondatum <= ?
|
||||
AND bisdatum>= ?";
|
||||
|
||||
if($nurblockierend)
|
||||
{
|
||||
$qry .= " AND zeitsperretyp_kurzbz IN ('"
|
||||
. implode("','", self::BLOCKIERENDE_ZEITSPERREN)
|
||||
. "')";
|
||||
}
|
||||
|
||||
if(!is_null($stunde))
|
||||
{
|
||||
$parametersArray = array_merge(
|
||||
$parametersArray,
|
||||
[$datum, $stunde, $datum, $datum, $stunde, $datum]
|
||||
);
|
||||
|
||||
$qry.=" AND
|
||||
((vondatum= ? AND vonstunde<= ? OR vonstunde is null OR vondatum<> ?) AND
|
||||
(bisdatum= ? AND bisstunde>= ? OR bisstunde is null OR bisdatum<> ?))";
|
||||
}
|
||||
|
||||
array_push($parametersArray, $uid);
|
||||
|
||||
$qry .= "AND mitarbeiter_uid= ? ";
|
||||
|
||||
return $this->execQuery($qry, $parametersArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* check a date for existing zeitsperre
|
||||
*
|
||||
* @param $uid mitarbeiteruid
|
||||
* @param $vondatum datum in Format IS0
|
||||
* @param $bisdatum datum in Format ISO
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function existsZeitaufzeichnung($uid, $vonDay, $bisDay)
|
||||
{
|
||||
try {
|
||||
$from = new DateTime($vonDay);
|
||||
$to = new DateTime($bisDay);
|
||||
} catch (Exception $e) {
|
||||
throw new Exception("Invalid date format");
|
||||
}
|
||||
|
||||
//remove hour stamps
|
||||
$from->setTime(0, 0, 0);
|
||||
$to->setTime(0, 0, 0)->modify('+1 day');
|
||||
|
||||
$fromSql = $from->format('Y-m-d');
|
||||
$toSql = $to->format('Y-m-d');
|
||||
$params = [$uid, $fromSql, $toSql];
|
||||
|
||||
$qry = "
|
||||
SELECT *
|
||||
FROM campus.tbl_zeitaufzeichnung
|
||||
WHERE uid = ?
|
||||
AND start >= ?
|
||||
AND ende < ? ";
|
||||
|
||||
$result = $this->execQuery($qry, $params);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ $includesArray = array(
|
||||
'skipID' => '#fhccontent',
|
||||
'vuedatepicker11' => true,
|
||||
'customCSSs' => array(
|
||||
'vendor/vuejs/vuedatepicker_css/main.css',
|
||||
'public/css/components/verticalsplit.css',
|
||||
'public/css/components/searchbar/searchbar.css',
|
||||
'public/css/Fhc.css',
|
||||
@@ -23,7 +24,9 @@ $includesArray = array(
|
||||
'public/css/components/FormUnderline.css',
|
||||
'public/css/components/abgabetool/abgabe.css',
|
||||
'public/css/Cis4/Cms.css',
|
||||
'public/css/Cis4/Studium.css'
|
||||
'public/css/Cis4/Studium.css',
|
||||
'public/css/Cis4/Benotungstool.css',
|
||||
'public/css/Cis4/Zeitsperren.css',
|
||||
),
|
||||
'customJSs' => array(
|
||||
'vendor/npm-asset/primevue/accordion/accordion.min.js',
|
||||
@@ -37,11 +40,15 @@ $includesArray = array(
|
||||
'vendor/npm-asset/primevue/timeline/timeline.min.js',
|
||||
'vendor/npm-asset/primevue/inplace/inplace.min.js',
|
||||
'vendor/npm-asset/primevue/message/message.min.js',
|
||||
'vendor/npm-asset/primevue/divider/divider.min.js',
|
||||
'vendor/npm-asset/primevue/password/password.js',
|
||||
'vendor/npm-asset/primevue/multiselect/multiselect.js',
|
||||
'vendor/npm-asset/primevue/tieredmenu/tieredmenu.js',
|
||||
'vendor/moment/luxonjs/luxon.min.js'
|
||||
),
|
||||
'customJSModules' => array(
|
||||
'public/js/apps/Cis/Cis.js',
|
||||
'vendor/olifolkerd/tabulator5/src/js/modules/ColumnCalcs/ColumnCalcs.js'
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?php
|
||||
$this->load->view(
|
||||
'templates/FHC-Header',
|
||||
array(
|
||||
$includesArray = array(
|
||||
'title' => 'Lehrauftrag bestellen',
|
||||
'jquery3' => true,
|
||||
'jqueryui1' => true,
|
||||
@@ -12,8 +10,15 @@ $this->load->view(
|
||||
'dialoglib' => true,
|
||||
'navigationwidget' => true,
|
||||
'addons' => true,
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$this->load->view(
|
||||
'templates/FHC-Header',
|
||||
$includesArray
|
||||
);
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<?php echo $this->widgetlib->widget('NavigationWidget'); ?>
|
||||
@@ -33,4 +38,12 @@ $this->load->view(
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php $this->load->view('templates/FHC-Footer'); ?>
|
||||
<?php
|
||||
|
||||
|
||||
$this->load->view(
|
||||
'templates/FHC-Footer',
|
||||
$includesArray
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
$this->load->view(
|
||||
'templates/FHC-Header',
|
||||
array(
|
||||
|
||||
$includesArray = array(
|
||||
'title' => 'Lehrauftrag bestellen',
|
||||
'jquery3' => true,
|
||||
'bootstrap3' => true,
|
||||
@@ -9,8 +8,13 @@ $this->load->view(
|
||||
'sbadmintemplate3' => true,
|
||||
'ajaxlib' => true,
|
||||
'navigationwidget' => true,
|
||||
)
|
||||
);
|
||||
|
||||
$this->load->view(
|
||||
'templates/FHC-Header',
|
||||
$includesArray
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
<?php echo $this->widgetlib->widget('NavigationWidget'); ?>
|
||||
@@ -34,4 +38,11 @@ $this->load->view(
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php $this->load->view('templates/FHC-Footer'); ?>
|
||||
<?php
|
||||
|
||||
$this->load->view(
|
||||
'templates/FHC-Footer',
|
||||
$includesArray
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
@@ -1,89 +1,101 @@
|
||||
<?php
|
||||
$this->load->view(
|
||||
'templates/FHC-Header',
|
||||
array(
|
||||
'title' => 'Lehrauftrag annehmen',
|
||||
'jquery3' => true,
|
||||
'jqueryui1' => true,
|
||||
'jquerycheckboxes1' => true,
|
||||
'bootstrap5' => true,
|
||||
'fontawesome6' => true,
|
||||
'sbadmintemplate' => false,
|
||||
'tabulator5' => true,
|
||||
'tabulator5JQuery' => true,
|
||||
'cis'=>true,
|
||||
'momentjs2' => true,
|
||||
'ajaxlib' => true,
|
||||
'dialoglib' => true,
|
||||
'tablewidget' => true,
|
||||
'phrases' => array(
|
||||
'global' => array(
|
||||
'lehrauftraegeAnnehmen',
|
||||
'dokumentePDF',
|
||||
'PDFLehrauftraegeFH',
|
||||
'PDFLehrauftraegeLehrgaenge'
|
||||
),
|
||||
'ui' => array(
|
||||
'anzeigen',
|
||||
'alleAnzeigen',
|
||||
'nurBestellteAnzeigen',
|
||||
'nurErteilteAnzeigen',
|
||||
'nurAngenommeneAnzeigen',
|
||||
'nurStornierteAnzeigen',
|
||||
'hilfeZuDieserSeite',
|
||||
'alleAuswaehlen',
|
||||
'alleAbwaehlen',
|
||||
'ausgewaehlteZeilen',
|
||||
'hilfe',
|
||||
'tabelleneinstellungen',
|
||||
'keineDatenVorhanden',
|
||||
'spaltenEinstellen',
|
||||
'bestelltVon',
|
||||
'erteiltVon',
|
||||
'angenommenVon',
|
||||
'storniertVon',
|
||||
'lehrauftragInBearbeitung',
|
||||
'wartetAufErteilung',
|
||||
'wartetAufErneuteErteilung',
|
||||
'letzterStatusBestellt',
|
||||
'letzterStatusErteilt',
|
||||
'letzterStatusAngenommen',
|
||||
'vertragWurdeStorniert',
|
||||
),
|
||||
'password' => array('password'),
|
||||
'dms' => array('informationsblattExterneLehrende'),
|
||||
'table' => array(
|
||||
'spaltenEinAusblenden',
|
||||
'spaltenEinAusblendenMitKlickOeffnen',
|
||||
'spaltenEinAusblendenAufEinstellungenKlicken',
|
||||
'spaltenEinAusblendenMitKlickAktivieren',
|
||||
'spaltenEinAusblendenMitKlickSchliessen',
|
||||
'spaltenbreiteVeraendern',
|
||||
'spaltenbreiteVeraendernText',
|
||||
'spaltenbreiteVeraendernInfotext',
|
||||
'zeilenAuswaehlen',
|
||||
'zeilenAuswaehlenEinzeln',
|
||||
'zeilenAuswaehlenBereich',
|
||||
'zeilenAuswaehlenAlle'
|
||||
),
|
||||
'lehre' => array(
|
||||
'lehrauftraegeAnnehmen',
|
||||
'lehrauftraegeAnnehmenText',
|
||||
'lehrauftraegeAnnehmenKlickStatusicon',
|
||||
'lehrauftraegeAnnehmenLehrauftraegeWaehlen',
|
||||
'lehrauftraegeAnnehmenMitKlickAnnehmen',
|
||||
'lehrauftraegeNichtAuswaehlbar',
|
||||
'lehrauftraegeNichtAuswaehlbarTextBeiAnnahme',
|
||||
'filterAlleBeiAnnahme',
|
||||
'filterErteiltBeiAnnahme',
|
||||
'filterAngenommen'
|
||||
)
|
||||
|
||||
$includesArray = array(
|
||||
'title' => 'Lehrauftrag annehmen',
|
||||
'jquery3' => true,
|
||||
'jqueryui1' => true,
|
||||
'jquerycheckboxes1' => true,
|
||||
'bootstrap5' => true,
|
||||
'fontawesome6' => true,
|
||||
'sbadmintemplate' => false,
|
||||
'tabulator5' => true,
|
||||
'tabulator5JQuery' => true,
|
||||
'cis'=>true,
|
||||
'momentjs2' => true,
|
||||
'ajaxlib' => true,
|
||||
'dialoglib' => true,
|
||||
'tablewidget' => true,
|
||||
'phrases' => array(
|
||||
'global' => array(
|
||||
'lehrauftraegeAnnehmen',
|
||||
'dokumentePDF',
|
||||
'PDFLehrauftraegeFH',
|
||||
'PDFLehrauftraegeLehrgaenge'
|
||||
),
|
||||
'customJSs' => array(
|
||||
'public/js/bootstrapper.js',
|
||||
'public/js/lehre/lehrauftrag/acceptLehrauftrag.js')
|
||||
'ui' => array(
|
||||
'anzeigen',
|
||||
'alleAnzeigen',
|
||||
'nurBestellteAnzeigen',
|
||||
'nurErteilteAnzeigen',
|
||||
'nurAngenommeneAnzeigen',
|
||||
'nurStornierteAnzeigen',
|
||||
'hilfeZuDieserSeite',
|
||||
'alleAuswaehlen',
|
||||
'alleAbwaehlen',
|
||||
'ausgewaehlteZeilen',
|
||||
'hilfe',
|
||||
'tabelleneinstellungen',
|
||||
'keineDatenVorhanden',
|
||||
'spaltenEinstellen',
|
||||
'bestelltVon',
|
||||
'erteiltVon',
|
||||
'angenommenVon',
|
||||
'storniertVon',
|
||||
'lehrauftragInBearbeitung',
|
||||
'wartetAufErteilung',
|
||||
'wartetAufErneuteErteilung',
|
||||
'letzterStatusBestellt',
|
||||
'letzterStatusErteilt',
|
||||
'letzterStatusAngenommen',
|
||||
'vertragWurdeStorniert',
|
||||
),
|
||||
'password' => array('password'),
|
||||
'dms' => array('informationsblattExterneLehrende'),
|
||||
'table' => array(
|
||||
'spaltenEinAusblenden',
|
||||
'spaltenEinAusblendenMitKlickOeffnen',
|
||||
'spaltenEinAusblendenAufEinstellungenKlicken',
|
||||
'spaltenEinAusblendenMitKlickAktivieren',
|
||||
'spaltenEinAusblendenMitKlickSchliessen',
|
||||
'spaltenbreiteVeraendern',
|
||||
'spaltenbreiteVeraendernText',
|
||||
'spaltenbreiteVeraendernInfotext',
|
||||
'zeilenAuswaehlen',
|
||||
'zeilenAuswaehlenEinzeln',
|
||||
'zeilenAuswaehlenBereich',
|
||||
'zeilenAuswaehlenAlle'
|
||||
),
|
||||
'lehre' => array(
|
||||
'lehrauftraegeAnnehmen',
|
||||
'lehrauftraegeAnnehmenText',
|
||||
'lehrauftraegeAnnehmenKlickStatusicon',
|
||||
'lehrauftraegeAnnehmenLehrauftraegeWaehlen',
|
||||
'lehrauftraegeAnnehmenMitKlickAnnehmen',
|
||||
'lehrauftraegeNichtAuswaehlbar',
|
||||
'lehrauftraegeNichtAuswaehlbarTextBeiAnnahme',
|
||||
'filterAlleBeiAnnahme',
|
||||
'filterErteiltBeiAnnahme',
|
||||
'filterAngenommen'
|
||||
)
|
||||
),
|
||||
'customJSs' => array(
|
||||
'public/js/bootstrapper.js',
|
||||
'public/js/lehre/lehrauftrag/acceptLehrauftrag.js'
|
||||
)
|
||||
);
|
||||
|
||||
if (defined("CIS4")) {
|
||||
$this->load->view(
|
||||
'templates/CISVUE-Header',
|
||||
$includesArray
|
||||
);
|
||||
} else {
|
||||
$this->load->view(
|
||||
'templates/FHC-Header',
|
||||
$includesArray
|
||||
);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
|
||||
@@ -230,5 +242,17 @@ $this->load->view(
|
||||
</div><!-- end page-wrapper -->
|
||||
<br>
|
||||
|
||||
<?php $this->load->view('templates/FHC-Footer'); ?>
|
||||
<?php
|
||||
if (defined("CIS4")) {
|
||||
$this->load->view(
|
||||
'templates/CISVUE-Footer',
|
||||
$includesArray
|
||||
);
|
||||
} else {
|
||||
$this->load->view(
|
||||
'templates/FHC-Footer',
|
||||
$includesArray
|
||||
);
|
||||
}
|
||||
?>
|
||||
|
||||
|
||||
@@ -1,98 +1,101 @@
|
||||
<?php
|
||||
$includesArray = array(
|
||||
'title' => 'Lehrauftrag erteilen',
|
||||
'jquery3' => true,
|
||||
'jqueryui1' => true,
|
||||
'jquerycheckboxes1' => true,
|
||||
'bootstrap3' => true,
|
||||
'fontawesome6' => true,
|
||||
'sbadmintemplate3' => true,
|
||||
'tabulator5' => true,
|
||||
'tabulator5JQuery' => true,
|
||||
'momentjs2' => true,
|
||||
'ajaxlib' => true,
|
||||
'dialoglib' => true,
|
||||
'tablewidget' => true,
|
||||
'navigationwidget' => true,
|
||||
'phrases' => array(
|
||||
'global' => array(
|
||||
'lehrauftraegeErteilen',
|
||||
'mehrHilfe',
|
||||
'weitereInformationenUnter'
|
||||
),
|
||||
'ui' => array(
|
||||
'anzeigen',
|
||||
'alleAnzeigen',
|
||||
'nurNeueAnzeigen',
|
||||
'nurBestellteAnzeigen',
|
||||
'nurErteilteAnzeigen',
|
||||
'nurAngenommeneAnzeigen',
|
||||
'nurGeaenderteAnzeigen',
|
||||
'nurDummiesAnzeigen',
|
||||
'hilfeZuDieserSeite',
|
||||
'alleAuswaehlen',
|
||||
'alleAbwaehlen',
|
||||
'ausgewaehlteZeilen',
|
||||
'hilfe',
|
||||
'tabelleneinstellungen',
|
||||
'keineDatenVorhanden',
|
||||
'spaltenEinstellen',
|
||||
'bestelltVon',
|
||||
'erteiltVon',
|
||||
'angenommenVon',
|
||||
'stundenStundensatzGeaendert',
|
||||
'neuerLehrauftragOhneLektorVerplant',
|
||||
'wartetAufBestellung',
|
||||
'wartetAufErneuteBestellung',
|
||||
'neuerLehrauftragWartetAufBestellung',
|
||||
'letzterStatusBestellt',
|
||||
'letzterStatusErteilt',
|
||||
'letzterStatusAngenommen',
|
||||
),
|
||||
'table' => array(
|
||||
'spaltenEinAusblenden',
|
||||
'spaltenEinAusblendenMitKlickOeffnen',
|
||||
'spaltenEinAusblendenAufEinstellungenKlicken',
|
||||
'spaltenEinAusblendenMitKlickAktivieren',
|
||||
'spaltenEinAusblendenMitKlickSchliessen',
|
||||
'spaltenbreiteVeraendern',
|
||||
'spaltenbreiteVeraendernText',
|
||||
'spaltenbreiteVeraendernInfotext',
|
||||
'zeilenAuswaehlen',
|
||||
'zeilenAuswaehlenEinzeln',
|
||||
'zeilenAuswaehlenBereich',
|
||||
'zeilenAuswaehlenAlle'
|
||||
),
|
||||
'lehre' => array(
|
||||
'lehrauftragStandardBestellprozess',
|
||||
'lehrauftragStandardBestellprozessBestellen',
|
||||
'lehrauftragStandardBestellprozessErteilen',
|
||||
'lehrauftragStandardBestellprozessAnnehmen',
|
||||
'lehrauftraegeErteilen',
|
||||
'lehrauftraegeErteilenText',
|
||||
'lehrauftraegeErteilenKlickStatusicon',
|
||||
'lehrauftraegeErteilenLehrauftraegeWaehlen',
|
||||
'lehrauftraegeErteilenMitKlickErteilen',
|
||||
'geaenderteLehrauftraege',
|
||||
'geaenderteLehrauftraegeTextBeiErteilung',
|
||||
'lehrauftraegeNichtAuswaehlbar',
|
||||
'lehrauftraegeNichtAuswaehlbarTextBeiErteilung',
|
||||
'filterAlle',
|
||||
'filterNeu',
|
||||
'filterBestellt',
|
||||
'filterErteilt',
|
||||
'filterAngenommen',
|
||||
'filterGeaendert',
|
||||
'filterDummies'
|
||||
)
|
||||
),
|
||||
'customJSs' => array(
|
||||
'public/js/bootstrapper.js',
|
||||
'public/js/lehre/lehrauftrag/approveLehrauftrag.js'
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$this->load->view(
|
||||
'templates/FHC-Header',
|
||||
array(
|
||||
'title' => 'Lehrauftrag erteilen',
|
||||
'jquery3' => true,
|
||||
'jqueryui1' => true,
|
||||
'jquerycheckboxes1' => true,
|
||||
'bootstrap3' => true,
|
||||
'fontawesome6' => true,
|
||||
'sbadmintemplate3' => true,
|
||||
'tabulator5' => true,
|
||||
'tabulator5JQuery' => true,
|
||||
'momentjs2' => true,
|
||||
'ajaxlib' => true,
|
||||
'dialoglib' => true,
|
||||
'tablewidget' => true,
|
||||
'navigationwidget' => true,
|
||||
'phrases' => array(
|
||||
'global' => array(
|
||||
'lehrauftraegeErteilen',
|
||||
'mehrHilfe',
|
||||
'weitereInformationenUnter'
|
||||
),
|
||||
'ui' => array(
|
||||
'anzeigen',
|
||||
'alleAnzeigen',
|
||||
'nurNeueAnzeigen',
|
||||
'nurBestellteAnzeigen',
|
||||
'nurErteilteAnzeigen',
|
||||
'nurAngenommeneAnzeigen',
|
||||
'nurGeaenderteAnzeigen',
|
||||
'nurDummiesAnzeigen',
|
||||
'hilfeZuDieserSeite',
|
||||
'alleAuswaehlen',
|
||||
'alleAbwaehlen',
|
||||
'ausgewaehlteZeilen',
|
||||
'hilfe',
|
||||
'tabelleneinstellungen',
|
||||
'keineDatenVorhanden',
|
||||
'spaltenEinstellen',
|
||||
'bestelltVon',
|
||||
'erteiltVon',
|
||||
'angenommenVon',
|
||||
'stundenStundensatzGeaendert',
|
||||
'neuerLehrauftragOhneLektorVerplant',
|
||||
'wartetAufBestellung',
|
||||
'wartetAufErneuteBestellung',
|
||||
'neuerLehrauftragWartetAufBestellung',
|
||||
'letzterStatusBestellt',
|
||||
'letzterStatusErteilt',
|
||||
'letzterStatusAngenommen',
|
||||
),
|
||||
'table' => array(
|
||||
'spaltenEinAusblenden',
|
||||
'spaltenEinAusblendenMitKlickOeffnen',
|
||||
'spaltenEinAusblendenAufEinstellungenKlicken',
|
||||
'spaltenEinAusblendenMitKlickAktivieren',
|
||||
'spaltenEinAusblendenMitKlickSchliessen',
|
||||
'spaltenbreiteVeraendern',
|
||||
'spaltenbreiteVeraendernText',
|
||||
'spaltenbreiteVeraendernInfotext',
|
||||
'zeilenAuswaehlen',
|
||||
'zeilenAuswaehlenEinzeln',
|
||||
'zeilenAuswaehlenBereich',
|
||||
'zeilenAuswaehlenAlle'
|
||||
),
|
||||
'lehre' => array(
|
||||
'lehrauftragStandardBestellprozess',
|
||||
'lehrauftragStandardBestellprozessBestellen',
|
||||
'lehrauftragStandardBestellprozessErteilen',
|
||||
'lehrauftragStandardBestellprozessAnnehmen',
|
||||
'lehrauftraegeErteilen',
|
||||
'lehrauftraegeErteilenText',
|
||||
'lehrauftraegeErteilenKlickStatusicon',
|
||||
'lehrauftraegeErteilenLehrauftraegeWaehlen',
|
||||
'lehrauftraegeErteilenMitKlickErteilen',
|
||||
'geaenderteLehrauftraege',
|
||||
'geaenderteLehrauftraegeTextBeiErteilung',
|
||||
'lehrauftraegeNichtAuswaehlbar',
|
||||
'lehrauftraegeNichtAuswaehlbarTextBeiErteilung',
|
||||
'filterAlle',
|
||||
'filterNeu',
|
||||
'filterBestellt',
|
||||
'filterErteilt',
|
||||
'filterAngenommen',
|
||||
'filterGeaendert',
|
||||
'filterDummies'
|
||||
)
|
||||
),
|
||||
'customJSs' => array(
|
||||
'public/js/bootstrapper.js',
|
||||
'public/js/lehre/lehrauftrag/approveLehrauftrag.js'
|
||||
)
|
||||
)
|
||||
'templates/FHC-Header',
|
||||
$includesArray
|
||||
);
|
||||
?>
|
||||
|
||||
@@ -208,5 +211,13 @@ $this->load->view(
|
||||
</div><!-- end page-wrapper -->
|
||||
<br>
|
||||
|
||||
<?php $this->load->view('templates/FHC-Footer'); ?>
|
||||
<?php
|
||||
|
||||
|
||||
$this->load->view(
|
||||
'templates/FHC-Footer',
|
||||
$includesArray
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
|
||||
@@ -1,98 +1,101 @@
|
||||
<?php
|
||||
$includesArray = array(
|
||||
'title' => 'Lehrauftrag bestellen',
|
||||
'jquery3' => true,
|
||||
'jqueryui1' => true,
|
||||
'jquerycheckboxes1' => true,
|
||||
'bootstrap3' => true,
|
||||
'fontawesome6' => true,
|
||||
'sbadmintemplate3' => true,
|
||||
'tabulator5' => true,
|
||||
'tabulator5JQuery' => true,
|
||||
'momentjs2' => true,
|
||||
'ajaxlib' => true,
|
||||
'dialoglib' => true,
|
||||
'tablewidget' => true,
|
||||
'navigationwidget' => true,
|
||||
'phrases' => array(
|
||||
'global' => array(
|
||||
'lehrauftraegeBestellen',
|
||||
'mehrHilfe',
|
||||
'weitereInformationenUnter'
|
||||
),
|
||||
'ui' => array(
|
||||
'anzeigen',
|
||||
'alleAnzeigen',
|
||||
'nurNeueAnzeigen',
|
||||
'nurBestellteAnzeigen',
|
||||
'nurErteilteAnzeigen',
|
||||
'nurAngenommeneAnzeigen',
|
||||
'nurGeaenderteAnzeigen',
|
||||
'nurDummiesAnzeigen',
|
||||
'hilfeZuDieserSeite',
|
||||
'alleAuswaehlen',
|
||||
'alleAbwaehlen',
|
||||
'ausgewaehlteZeilen',
|
||||
'hilfe',
|
||||
'tabelleneinstellungen',
|
||||
'keineDatenVorhanden',
|
||||
'spaltenEinstellen',
|
||||
'bestelltVon',
|
||||
'erteiltVon',
|
||||
'angenommenVon',
|
||||
'neuerLehrauftragOhneLektorVerplant',
|
||||
'neuerLehrauftragWartetAufBestellung',
|
||||
'letzterStatusBestellt',
|
||||
'letzterStatusErteilt',
|
||||
'letzterStatusAngenommen',
|
||||
'nachAenderungStundensatzStunden',
|
||||
'vorAenderungStundensatzStunden'
|
||||
),
|
||||
'table' => array(
|
||||
'spaltenEinAusblenden',
|
||||
'spaltenEinAusblendenMitKlickOeffnen',
|
||||
'spaltenEinAusblendenAufEinstellungenKlicken',
|
||||
'spaltenEinAusblendenMitKlickAktivieren',
|
||||
'spaltenEinAusblendenMitKlickSchliessen',
|
||||
'spaltenbreiteVeraendern',
|
||||
'spaltenbreiteVeraendernText',
|
||||
'spaltenbreiteVeraendernInfotext',
|
||||
'zeilenAuswaehlen',
|
||||
'zeilenAuswaehlenEinzeln',
|
||||
'zeilenAuswaehlenBereich',
|
||||
'zeilenAuswaehlenAlle'
|
||||
),
|
||||
'lehre' => array(
|
||||
'lehrauftragStandardBestellprozess',
|
||||
'lehrauftragStandardBestellprozessBestellen',
|
||||
'lehrauftragStandardBestellprozessErteilen',
|
||||
'lehrauftragStandardBestellprozessAnnehmen',
|
||||
'lehrauftraegeBestellen',
|
||||
'lehrauftraegeBestellenText',
|
||||
'lehrauftraegeBestellenKlickStatusicon',
|
||||
'lehrauftraegeBestellenLehrauftraegeWaehlen',
|
||||
'lehrauftraegeBestellenMitKlickBestellen',
|
||||
'lehrauftraegeBestellenVertragWirdAngelegt',
|
||||
'geaenderteLehrauftraege',
|
||||
'geaenderteLehrauftraegeText',
|
||||
'lehrauftraegeNichtAuswaehlbar',
|
||||
'lehrauftraegeNichtAuswaehlbarText',
|
||||
'filterAlle',
|
||||
'filterNeu',
|
||||
'filterBestellt',
|
||||
'filterErteilt',
|
||||
'filterAngenommen',
|
||||
'filterGeaendert',
|
||||
'filterDummies'
|
||||
)
|
||||
),
|
||||
'customJSs' => array(
|
||||
'public/js/bootstrapper.js',
|
||||
'public/js/lehre/lehrauftrag/orderLehrauftrag.js'
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
$this->load->view(
|
||||
'templates/FHC-Header',
|
||||
array(
|
||||
'title' => 'Lehrauftrag bestellen',
|
||||
'jquery3' => true,
|
||||
'jqueryui1' => true,
|
||||
'jquerycheckboxes1' => true,
|
||||
'bootstrap3' => true,
|
||||
'fontawesome6' => true,
|
||||
'sbadmintemplate3' => true,
|
||||
'tabulator5' => true,
|
||||
'tabulator5JQuery' => true,
|
||||
'momentjs2' => true,
|
||||
'ajaxlib' => true,
|
||||
'dialoglib' => true,
|
||||
'tablewidget' => true,
|
||||
'navigationwidget' => true,
|
||||
'phrases' => array(
|
||||
'global' => array(
|
||||
'lehrauftraegeBestellen',
|
||||
'mehrHilfe',
|
||||
'weitereInformationenUnter'
|
||||
),
|
||||
'ui' => array(
|
||||
'anzeigen',
|
||||
'alleAnzeigen',
|
||||
'nurNeueAnzeigen',
|
||||
'nurBestellteAnzeigen',
|
||||
'nurErteilteAnzeigen',
|
||||
'nurAngenommeneAnzeigen',
|
||||
'nurGeaenderteAnzeigen',
|
||||
'nurDummiesAnzeigen',
|
||||
'hilfeZuDieserSeite',
|
||||
'alleAuswaehlen',
|
||||
'alleAbwaehlen',
|
||||
'ausgewaehlteZeilen',
|
||||
'hilfe',
|
||||
'tabelleneinstellungen',
|
||||
'keineDatenVorhanden',
|
||||
'spaltenEinstellen',
|
||||
'bestelltVon',
|
||||
'erteiltVon',
|
||||
'angenommenVon',
|
||||
'neuerLehrauftragOhneLektorVerplant',
|
||||
'neuerLehrauftragWartetAufBestellung',
|
||||
'letzterStatusBestellt',
|
||||
'letzterStatusErteilt',
|
||||
'letzterStatusAngenommen',
|
||||
'nachAenderungStundensatzStunden',
|
||||
'vorAenderungStundensatzStunden'
|
||||
),
|
||||
'table' => array(
|
||||
'spaltenEinAusblenden',
|
||||
'spaltenEinAusblendenMitKlickOeffnen',
|
||||
'spaltenEinAusblendenAufEinstellungenKlicken',
|
||||
'spaltenEinAusblendenMitKlickAktivieren',
|
||||
'spaltenEinAusblendenMitKlickSchliessen',
|
||||
'spaltenbreiteVeraendern',
|
||||
'spaltenbreiteVeraendernText',
|
||||
'spaltenbreiteVeraendernInfotext',
|
||||
'zeilenAuswaehlen',
|
||||
'zeilenAuswaehlenEinzeln',
|
||||
'zeilenAuswaehlenBereich',
|
||||
'zeilenAuswaehlenAlle'
|
||||
),
|
||||
'lehre' => array(
|
||||
'lehrauftragStandardBestellprozess',
|
||||
'lehrauftragStandardBestellprozessBestellen',
|
||||
'lehrauftragStandardBestellprozessErteilen',
|
||||
'lehrauftragStandardBestellprozessAnnehmen',
|
||||
'lehrauftraegeBestellen',
|
||||
'lehrauftraegeBestellenText',
|
||||
'lehrauftraegeBestellenKlickStatusicon',
|
||||
'lehrauftraegeBestellenLehrauftraegeWaehlen',
|
||||
'lehrauftraegeBestellenMitKlickBestellen',
|
||||
'lehrauftraegeBestellenVertragWirdAngelegt',
|
||||
'geaenderteLehrauftraege',
|
||||
'geaenderteLehrauftraegeText',
|
||||
'lehrauftraegeNichtAuswaehlbar',
|
||||
'lehrauftraegeNichtAuswaehlbarText',
|
||||
'filterAlle',
|
||||
'filterNeu',
|
||||
'filterBestellt',
|
||||
'filterErteilt',
|
||||
'filterAngenommen',
|
||||
'filterGeaendert',
|
||||
'filterDummies'
|
||||
)
|
||||
),
|
||||
'customJSs' => array(
|
||||
'public/js/bootstrapper.js',
|
||||
'public/js/lehre/lehrauftrag/orderLehrauftrag.js'
|
||||
)
|
||||
)
|
||||
'templates/FHC-Header',
|
||||
$includesArray
|
||||
);
|
||||
?>
|
||||
|
||||
@@ -209,5 +212,11 @@ $this->load->view(
|
||||
</div><!-- end page-wrapper -->
|
||||
<br>
|
||||
|
||||
<?php $this->load->view('templates/FHC-Footer'); ?>
|
||||
<?php
|
||||
|
||||
$this->load->view(
|
||||
'templates/FHC-Footer',
|
||||
$includesArray
|
||||
);
|
||||
?>
|
||||
|
||||
|
||||
@@ -9,22 +9,8 @@ $sitesettings = array(
|
||||
'ajaxlib' => true,
|
||||
'sbadmintemplate3' => true,
|
||||
'phrases' => array(
|
||||
'abschlusspruefung' => array(
|
||||
'freigegebenAm',
|
||||
'pruefungGespeichert',
|
||||
'pruefungSpeichernFehler',
|
||||
'abschlussbeurteilungLeer',
|
||||
'beginnzeitLeer',
|
||||
'beginnzeitFormatError',
|
||||
'endezeitLeer',
|
||||
'endezeitFormatError',
|
||||
'endezeitBeforeError',
|
||||
'verfNotice'
|
||||
),
|
||||
'ui' => array(
|
||||
'stunde',
|
||||
'minute'
|
||||
)
|
||||
'abschlusspruefung',
|
||||
'ui'
|
||||
),
|
||||
'customCSSs' => array(
|
||||
'public/css/sbadmin2/admintemplate_contentonly.css',
|
||||
@@ -37,10 +23,18 @@ $sitesettings = array(
|
||||
)
|
||||
);
|
||||
|
||||
$this->load->view(
|
||||
'templates/FHC-Header',
|
||||
$sitesettings
|
||||
);
|
||||
if(defined('CIS4')){
|
||||
$this->load->view(
|
||||
'templates/CISVUE-Header',
|
||||
$sitesettings
|
||||
);
|
||||
}else{
|
||||
$this->load->view(
|
||||
'templates/FHC-Header',
|
||||
$sitesettings
|
||||
);
|
||||
}
|
||||
|
||||
?>
|
||||
<div id="wrapper">
|
||||
<div id="page-wrapper">
|
||||
@@ -161,6 +155,14 @@ $this->load->view(
|
||||
<?php echo ($abschlusspruefung->studiengangstyp == 'Bachelor' ? $this->p->t('abschlusspruefung', 'pruefungsgegenstandBachelor') : $this->p->t('abschlusspruefung', 'pruefungsgegenstandMaster')) ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<?php echo $this->p->t('abschlusspruefung', 'spracheDerArbeit') ?> <?php echo $arbeit_name ?>
|
||||
</td>
|
||||
<td colspan="5">
|
||||
<?php echo $abschlusspruefung->abschlussarbeit_sprache ?? '' ?>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6">
|
||||
<?php echo ucfirst($this->p->t('global', 'notizen')); ?>
|
||||
@@ -201,7 +203,9 @@ $this->load->view(
|
||||
<div class="col-lg-12 text-right">
|
||||
<p>
|
||||
<?php $freigegeben = isset($abschlusspruefung->freigabedatum); ?>
|
||||
<button id="saveProtocolBtn" class="btn btn-default"<?php echo $freigegeben ? " disabled" : "" ?>><?php echo $this->p->t('ui', 'speichern') ?></button>
|
||||
<button id="saveProtocolBtn" class="btn btn-default"<?php echo $freigegeben ? ' disabled title="'.$this->p->t('abschlusspruefung', 'bereitsFreigegeben').'"' : '' ?>>
|
||||
<?php echo $this->p->t('ui', 'speichern') ?>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -236,7 +240,14 @@ $this->load->view(
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
$this->load->view(
|
||||
'templates/FHC-Footer',
|
||||
$sitesettings
|
||||
);
|
||||
if (defined('CIS4')) {
|
||||
$this->load->view(
|
||||
'templates/CISVUE-Footer',
|
||||
$sitesettings
|
||||
);
|
||||
} else {
|
||||
$this->load->view(
|
||||
'templates/FHC-Footer',
|
||||
$sitesettings
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<div class="navbar-default sidebar" role="navigation">
|
||||
<div class="navbar-default sidebar top-0" role="navigation">
|
||||
<div class="sidebar-nav navbar-collapse">
|
||||
<ul class="nav" id="side-menu"></ul>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/* 1. Stick the Header */
|
||||
#notentable .tabulator-header .tabulator-col.sticky-col {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
z-index: 10; /* Must be higher than other headers */
|
||||
background-color: #fff; /* Opaque background is required */
|
||||
border-right: 2px solid #ddd; /* Optional: Separator line */
|
||||
}
|
||||
|
||||
/* 2. Stick the Data Cells */
|
||||
#notentable .tabulator-tableholder .tabulator-row .tabulator-cell.sticky-col {
|
||||
position: sticky;
|
||||
left: 0;
|
||||
z-index: 10; /* Ensure it floats above other cells */
|
||||
background-color: #fff; /* Match your row background color */
|
||||
border-right: 2px solid #ddd; /* Optional: Separator line */
|
||||
}
|
||||
|
||||
/* 3. Fix for Hover Effects (Optional) */
|
||||
/* If you use hover rows, you need to ensure the sticky cell matches the hover color */
|
||||
#notentable .tabulator-row:hover .tabulator-cell.sticky-col {
|
||||
background-color: #ccc; /* Match your existing hover color */
|
||||
}
|
||||
|
||||
|
||||
/* styling for points input column for notenvorschläge in benotungstool*/
|
||||
#notentable .tabulator-tableholder .tabulator-editable[tabulator-field="punkte"] {
|
||||
position: relative;
|
||||
background-color: rgba(255, 255, 157, 0.73);
|
||||
}
|
||||
|
||||
/* styling for editable dropdown column of notenvorschläge in benotungstool*/
|
||||
#notentable .tabulator-tableholder .tabulator-editable[tabulator-field="note_vorschlag"] {
|
||||
position: relative;
|
||||
background-color: rgba(255, 255, 157, 0.73);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#notentable .tabulator-tableholder .tabulator-editable[tabulator-field="note_vorschlag"]::after {
|
||||
content: "▾";
|
||||
position: absolute;
|
||||
right: 6px;
|
||||
color: rgba(176, 176, 106, 0.73);;
|
||||
font-size: x-large;
|
||||
bottom: 6px;
|
||||
pointer-events: none;
|
||||
}
|
||||
@@ -97,3 +97,17 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.fhc-calendar-empty-slot-plus {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
font-size: 18px;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.part-body:hover .fhc-calendar-empty-slot-plus {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/* Repositioning clear icon Datepicker for not being outside the textfield */
|
||||
/* Wrapper */
|
||||
.dp__input_wrap {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* calender-Icon left */
|
||||
.dp__input_icon {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
right: auto;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
/* Clear-Icon right */
|
||||
.dp__clear_icon {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
left: auto;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
/* padding for Icons */
|
||||
.dp__input {
|
||||
padding-left: 36px !important;
|
||||
padding-right: 36px !important;
|
||||
}
|
||||
|
||||
.info-feedback {
|
||||
display: block;
|
||||
font-size: 0.875em;
|
||||
color: #0d6efd; /* Bootstrap primary */
|
||||
}
|
||||
|
||||
.is-info {
|
||||
border-color: #0d6efd;
|
||||
}
|
||||
@@ -6,3 +6,13 @@
|
||||
color: var(--fhc-myLv-disabled) !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* adjustment to have bs5 dropdownmenus rendered properly over a tabulator table */
|
||||
.mylv-semester-table .tabulator-cell {
|
||||
overflow: unset;
|
||||
}
|
||||
|
||||
.mylv-semester-table .tabulator-cell .action-col {
|
||||
/*min-height: 2.5rem;*/
|
||||
align-items: flex-start; /* so wrapped rows don't stretch vertically */
|
||||
}
|
||||
@@ -21,5 +21,20 @@ export default {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/LvMenu/getLvMenu/${lvid}/${studiensemester_kurzbz}`
|
||||
};
|
||||
},
|
||||
getMultipleLvMenu(lvas, studiensemester_kurzbz) {
|
||||
// format params for backend bulk function
|
||||
const lvMenuOptionList = lvas.map(lva => {
|
||||
return {
|
||||
lvid: lva.lehrveranstaltung_id,
|
||||
studiensemester_kurzbz
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
method: 'post',
|
||||
url: `/api/frontend/v1/LvMenu/getMultipleLvMenu`,
|
||||
params: { lvMenuOptionList }
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,44 @@
|
||||
export default {
|
||||
getReservableMap(ort_kurzbz, start_date, end_date) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: `/api/frontend/v1/calendar/RoomPlan/getReservableMap/${ort_kurzbz}`,
|
||||
params: { start_date, end_date }
|
||||
};
|
||||
},
|
||||
|
||||
getRoomCreationInfo() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/calendar/RoomPlan/getRoomCreationInfo'
|
||||
};
|
||||
},
|
||||
getGruppen(query) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/calendar/RoomPlan/getGruppen?query=${encodeURIComponent(query)}`
|
||||
};
|
||||
},
|
||||
getLektor(query) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/calendar/RoomPlan/getLektor?query=${encodeURIComponent(query)}`
|
||||
};
|
||||
},
|
||||
addRoomReservation(formData) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/calendar/RoomPlan/addRoomReservation',
|
||||
params: formData
|
||||
};
|
||||
},
|
||||
deleteRoomReservation(reservierung_id) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/calendar/RoomPlan/deleteRoomReservation',
|
||||
params: {
|
||||
reservierung_id: reservierung_id
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Copyright (C) 2026 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
getTimelocksUser(uid) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Zeitsperren/getZeitsperrenUser/' + uid
|
||||
};
|
||||
},
|
||||
getTypenZeitsperren(){
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Zeitsperren/getTypenZeitsperren/'
|
||||
};
|
||||
},
|
||||
getTypenErreichbarkeit(){
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Zeitsperren/getTypenErreichbarkeit/'
|
||||
};
|
||||
},
|
||||
getStunden(){
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Zeitsperren/getStunden/'
|
||||
};
|
||||
},
|
||||
addZeitsperre(uid, params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Zeitsperren/add/' + uid,
|
||||
params
|
||||
};
|
||||
},
|
||||
editZeitsperre(zeitsperre_id, params) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Zeitsperren/update/' + zeitsperre_id,
|
||||
params
|
||||
};
|
||||
},
|
||||
loadZeitsperre(zeitsperre_id) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Zeitsperren/loadZeitsperre/' + zeitsperre_id
|
||||
};
|
||||
},
|
||||
deleteZeitsperre(zeitsperre_id) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Zeitsperren/delete/' + zeitsperre_id
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
@@ -41,5 +41,19 @@ export default {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/Lehre/semesterAverageGrade/${semester}`
|
||||
}
|
||||
},
|
||||
getZugewieseneLv(uid, sem_kurzbz){
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Lehre/getZugewieseneLv',
|
||||
params: { uid, sem_kurzbz}
|
||||
};
|
||||
},
|
||||
getLeForLv(lv_id, sem_kurzbz) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Lehre/getLeForLv',
|
||||
params: { lv_id, sem_kurzbz }
|
||||
};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Copyright (C) 2025 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
getCisConfig(){
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Noten/getCisConfig'
|
||||
};
|
||||
},
|
||||
getStudentenNoten(lv_id, sem_kurzbz) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Noten/getStudentenNoten',
|
||||
params: { lv_id, sem_kurzbz }
|
||||
};
|
||||
},
|
||||
getNoten(){
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Noten/getNoten'
|
||||
};
|
||||
},
|
||||
saveStudentenNoten(password, noten, lv_id, sem_kurzbz) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/saveStudentenNoten',
|
||||
params: { password, noten, lv_id, sem_kurzbz }
|
||||
};
|
||||
},
|
||||
saveNotenvorschlag(lv_id, sem_kurzbz, student_uid, note, punkte = null) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/saveNotenvorschlag',
|
||||
params: { lv_id, sem_kurzbz, student_uid, note, punkte }
|
||||
};
|
||||
},
|
||||
saveStudentPruefung(student_uid, note, punkte, datum, lva_id, lehreinheit_id, sem_kurzbz, typ){
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/saveStudentPruefung',
|
||||
params: { student_uid, note, punkte, datum, lva_id, lehreinheit_id, sem_kurzbz, typ }
|
||||
};
|
||||
},
|
||||
createPruefungen(uids, datum, lva_id, sem_kurzbz){
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/createPruefungen',
|
||||
params: { uids, datum, lva_id, sem_kurzbz }
|
||||
};
|
||||
},
|
||||
saveNotenvorschlagBulk(lv_id, sem_kurzbz, noten) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/saveNotenvorschlagBulk',
|
||||
params: { lv_id, sem_kurzbz, noten }
|
||||
};
|
||||
},
|
||||
saveStudentPruefungBulk(lv_id, sem_kurzbz, pruefungen) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/savePruefungenBulk',
|
||||
params: { lv_id, sem_kurzbz, pruefungen }
|
||||
};
|
||||
},
|
||||
getNoteByPunkte(punkte, lv_id, sem_kurzbz) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/getNoteByPunkte',
|
||||
params: { punkte, lv_id, sem_kurzbz }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
export default {
|
||||
getPaAbgaben(studiengang_kz, abgabetyp_kurzbz, abgabedatum, personSearchString) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/education/PaabgabeUebersicht/getPaAbgaben',
|
||||
params: {
|
||||
studiengang_kz: studiengang_kz, abgabetyp_kurzbz: abgabetyp_kurzbz, abgabedatum: abgabedatum, personSearchString: personSearchString
|
||||
}
|
||||
};
|
||||
},
|
||||
getStudiengaenge() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/education/PaabgabeUebersicht/getStudiengaenge'
|
||||
};
|
||||
},
|
||||
getTermine(studiengang_kz, abgabetyp_kurzbz) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/education/PaabgabeUebersicht/getTermine',
|
||||
params: { studiengang_kz: studiengang_kz, abgabetyp_kurzbz: abgabetyp_kurzbz }
|
||||
};
|
||||
},
|
||||
getPaAbgabetypen() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/education/PaabgabeUebersicht/getPaAbgabetypen'
|
||||
};
|
||||
},
|
||||
getViewData() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/education/PaabgabeUebersicht/viewData'
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -29,5 +29,11 @@ export default {
|
||||
url: 'api/frontend/v1/organisation/studiensemester/getAll',
|
||||
params: { order, start }
|
||||
};
|
||||
}
|
||||
},
|
||||
getStudiensemester() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Studiensemester/getStudiensemester'
|
||||
};
|
||||
},
|
||||
};
|
||||
+40
-10
@@ -5,7 +5,7 @@ import contrast from '../../directives/contrast.js';
|
||||
import {setScrollbarWidth} from "../../helpers/CssVarCalcHelpers.js";
|
||||
import LvPlan from "../../components/Cis/LvPlan/Lehrveranstaltung.js";
|
||||
import MyLvPlan from "../../components/Cis/LvPlan/MyLvPlan.js";
|
||||
import MylvStudent from "../../components/Cis/Mylv/Student.js";
|
||||
import Mylv from "../../components/Cis/Mylv/MyLv.js";
|
||||
import Profil from "../../components/Cis/Profil/Profil.js";
|
||||
import Raumsuche from "../../components/Cis/Raumsuche/Raumsuche.js";
|
||||
import CmsNews from "../../components/Cis/Cms/News.js";
|
||||
@@ -19,9 +19,13 @@ import DeadlineOverview from "../../components/Cis/Abgabetool/DeadlineOverview.j
|
||||
import Studium from "../../components/Cis/Studium/Studium.js";
|
||||
import StgOrgLvPlan from "../../components/Cis/LvPlan/StgOrg.js";
|
||||
import OtherLvPlan from "../../components/Cis/LvPlan/OtherLvPlan.js";
|
||||
import PaabgabeUebersicht from "../../components/Cis/ProjektabgabeUebersicht/ProjektabgabeUebersicht.js";
|
||||
import Benotungstool from "../../components/Cis/Benotungstool/Benotungstool.js";
|
||||
import Zeitsperren from "../../components/Cis/Zeitsperren/Zeitsperren.js";
|
||||
|
||||
import ApiRouteInfo from '../../api/factory/routeinfo.js';
|
||||
import {capitalize} from "../../helpers/StringHelpers.js";
|
||||
import ApiAuthinfo from "../../api/factory/authinfo.js";
|
||||
|
||||
const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
|
||||
const isMobile = window.matchMedia("(max-width: 767px)").matches;
|
||||
@@ -77,6 +81,18 @@ const router = VueRouter.createRouter({
|
||||
component: Raumsuche,
|
||||
props: true
|
||||
},
|
||||
{
|
||||
path: `/Cis/ProjektabgabeUebersicht`,
|
||||
name: 'PaabgabeUebersicht',
|
||||
component: PaabgabeUebersicht,
|
||||
props: true
|
||||
},
|
||||
{
|
||||
path: `/Cis/Benotungstool/:lv_id/:sem_kurzbz`,
|
||||
name: 'Benotungstool',
|
||||
component: Benotungstool,
|
||||
props: true
|
||||
},
|
||||
// Redirect old links to new format
|
||||
{
|
||||
path: "/CisVue/Cms/getRoomInformation/:ort_kurzbz",
|
||||
@@ -151,7 +167,7 @@ const router = VueRouter.createRouter({
|
||||
{
|
||||
path: `/Cis/MyLv/:studiensemester?`,
|
||||
name: 'MyLv',
|
||||
component: MylvStudent,
|
||||
component: Mylv,
|
||||
props: true,
|
||||
},
|
||||
{
|
||||
@@ -163,7 +179,7 @@ const router = VueRouter.createRouter({
|
||||
// Redirect old links to new format
|
||||
{
|
||||
// only trigger on first param being numeric to avoid paths like "LvPlan/Month" entering here
|
||||
path: "/Cis/LvPlan/:lv_id(\\d+)",
|
||||
path: "/Cis/LvPlan/:lv_id(\\d+)",
|
||||
name: "LvPlanOld",
|
||||
component: LvPlan,
|
||||
redirect(to) {
|
||||
@@ -245,6 +261,12 @@ const router = VueRouter.createRouter({
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
path: `/Cis/Zeitsperren`,
|
||||
name: 'Zeitsperren',
|
||||
component: Zeitsperren,
|
||||
props: true
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
@@ -253,11 +275,15 @@ const app = Vue.createApp({
|
||||
data: () => ({
|
||||
appSideMenuEntries: {},
|
||||
windowWidth: 0,
|
||||
isStudent: null,
|
||||
isMitarbeiter: null,
|
||||
}),
|
||||
provide() {
|
||||
return { // provide injectable & watchable language property
|
||||
language: Vue.computed(() => this.$p.user_language),
|
||||
isMobile: Vue.computed(() => this.windowWidth < 767),
|
||||
isStudent: Vue.computed(() => this.isStudent),
|
||||
isMitarbeiter: Vue.computed(() => this.isMitarbeiter)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -271,7 +297,7 @@ const app = Vue.createApp({
|
||||
if(target?.id == 'skiplink') return
|
||||
if (target && this.isInternalRoute(target.href)) {
|
||||
const url = new URL(target.href)
|
||||
|
||||
|
||||
const path = url.pathname
|
||||
const base = this.$router.options.history.base
|
||||
const route = path.replace(base, '') || '/'
|
||||
@@ -279,27 +305,31 @@ const app = Vue.createApp({
|
||||
// let click event propagate normally if we dont route internally
|
||||
const res = this.$router.resolve(route)
|
||||
if(!res?.matched?.length || res.name === 'Fallback') return
|
||||
|
||||
|
||||
event.preventDefault(); // Prevent browser navigation
|
||||
|
||||
|
||||
if(this.isMobile) { // toggle the menu
|
||||
const navMain = document.getElementById('nav-main');
|
||||
// fix unwanted toggle from off to on for some links on mobile
|
||||
if(navMain.classList.contains('show')){
|
||||
document.getElementById('nav-main-btn').click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.$router.push(route);
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
handleWindowResize() {
|
||||
this.windowWidth = window.innerWidth;
|
||||
},
|
||||
},
|
||||
created() {
|
||||
async created() {
|
||||
this.windowWidth = window.innerWidth;
|
||||
await this.$api.call(ApiAuthinfo.getAuthInfo()).then((res) => {
|
||||
this.isMitarbeiter = res.data.isMitarbeiter;
|
||||
this.isStudent = res.data.isStudent;
|
||||
});
|
||||
},
|
||||
async mounted() {
|
||||
document.addEventListener('click', this.handleClick);
|
||||
|
||||
@@ -148,4 +148,4 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
@@ -44,7 +44,10 @@ export default {
|
||||
return () => true;
|
||||
}),
|
||||
hasDragoverFunc: Vue.computed(() => this.onDragover),
|
||||
mode: Vue.computed(() => this.mode)
|
||||
mode: Vue.computed(() => this.mode),
|
||||
reservierbarMap: Vue.computed(() => this.reservierbarMap),
|
||||
isReservierbar: Vue.computed(() => this.isReservierbar),
|
||||
createContext: Vue.computed(() => this.createContext)
|
||||
};
|
||||
},
|
||||
props: {
|
||||
@@ -97,7 +100,13 @@ export default {
|
||||
draggableEvents: [Boolean, Array, Function],
|
||||
dropableEvents: [Boolean, Array, Function],
|
||||
onDragover: Function,
|
||||
onDrop: Function
|
||||
onDrop: Function,
|
||||
isReservierbar: Boolean,
|
||||
createContext: Object,
|
||||
reservierbarMap: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
"click:next",
|
||||
@@ -105,11 +114,13 @@ export default {
|
||||
"click:mode",
|
||||
"click:event",
|
||||
"click:day",
|
||||
"click:slot",
|
||||
"click:week",
|
||||
"update:date",
|
||||
"update:mode",
|
||||
"update:range",
|
||||
"drop"
|
||||
"drop",
|
||||
"create-event"
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -2,6 +2,7 @@ import GridLine from './Grid/Line.js';
|
||||
import GridLineEvent from './Grid/Line/Event.js';
|
||||
|
||||
import CalDnd from '../../../directives/Calendar/DragAndDrop.js';
|
||||
import CalClick from '../../../directives/Calendar/Click.js';
|
||||
|
||||
export default {
|
||||
name: "CalendarGrid",
|
||||
@@ -10,12 +11,16 @@ export default {
|
||||
GridLineEvent
|
||||
},
|
||||
directives: {
|
||||
CalDnd
|
||||
CalDnd,
|
||||
CalClick
|
||||
},
|
||||
inject: {
|
||||
originalEvents: "events",
|
||||
originalBackgrounds: "backgrounds",
|
||||
dropAllowed: "dropAllowed"
|
||||
dropAllowed: "dropAllowed",
|
||||
timezone: "timezone",
|
||||
reservierbar: "isReservierbar",
|
||||
reservierbarMap: "reservierbarMap",
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
@@ -308,8 +313,25 @@ export default {
|
||||
} else {
|
||||
this.$refs.scroller.scrollTo(0, 0);
|
||||
}
|
||||
},
|
||||
isFreeSlot(date, part, dayEvents) {
|
||||
const pastEnd = luxon.DateTime.now().setZone(this.timezone);
|
||||
|
||||
const start = date.plus(part.start || part);
|
||||
const end = date.plus(part.end || part.plus({ hours: 1 }));
|
||||
|
||||
if (start < pastEnd)
|
||||
return false;
|
||||
|
||||
if (!dayEvents || !dayEvents.length)
|
||||
return true;
|
||||
|
||||
return !dayEvents.some(ev => ev.start < end && ev.end > start);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$p.loadCategory(["LvPlan"]);
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.disableAutoScroll();
|
||||
},
|
||||
@@ -400,6 +422,20 @@ export default {
|
||||
:style="'grid-' + axisCol + ':' + (1+index) + ';grid-' + axisRow + ':ps_' + i + '/pe_' + i"
|
||||
>
|
||||
<slot name="part-body" v-bind="{ index, part }" />
|
||||
|
||||
<div
|
||||
v-if="isFreeSlot(date, part, eventsNormal[index]) && reservierbar"
|
||||
class="fhc-calendar-empty-slot"
|
||||
style="position:absolute; inset:0; z-index:1"
|
||||
v-cal-click:slot="{ date, part }"
|
||||
:title="this.reservierbarMap?.[date.toISODate()] ? $p.t('LvPlan/add_reservation') : $p.t('LvPlan/reservation_not_allowed')"
|
||||
>
|
||||
<div class="fhc-calendar-empty-slot-plus">
|
||||
<i v-if="this.reservierbarMap?.[date.toISODate()]" class="fa-solid fa-plus"></i>
|
||||
<i v-else class="fa-solid fa-ban" style="color: red;"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="snapToGrid && dragging"
|
||||
style="position:absolute;inset:0;z-index:1"
|
||||
|
||||
@@ -28,7 +28,15 @@ export default {
|
||||
getPromiseFunc: {
|
||||
type: Function,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
reservierbar: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
createContext: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
@@ -43,11 +51,26 @@ export default {
|
||||
emits: [
|
||||
"update:date",
|
||||
"update:mode",
|
||||
"update:range"
|
||||
"update:range",
|
||||
"create-event",
|
||||
"delete-event",
|
||||
'update:reservierbarMap'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
timezone: FHC_JS_DATA_STORAGE_OBJECT.timezone,
|
||||
isReservierbar: Vue.computed(() => {
|
||||
if (!this.reservierbar)
|
||||
return false;
|
||||
|
||||
if (!this.reservierbarMap)
|
||||
return false;
|
||||
|
||||
if (typeof this.reservierbarMap === 'object')
|
||||
return Object.keys(this.reservierbarMap).length > 0;
|
||||
|
||||
return false;
|
||||
}),
|
||||
modeOptions: {
|
||||
day: {
|
||||
emptyMessage: Vue.computed(() => this.$p.t('lehre/noLvFound')),
|
||||
@@ -125,11 +148,14 @@ export default {
|
||||
);
|
||||
this.compactibleEventTypes = compactibleEventTypesResponse.data;
|
||||
},
|
||||
closeModal() {
|
||||
this.$refs.calendar.hideEventModal();
|
||||
},
|
||||
},
|
||||
setup(props, context) {
|
||||
const rangeInterval = Vue.ref(null);
|
||||
|
||||
const { events, lv, reset } = useEventLoader(rangeInterval, props.getPromiseFunc);
|
||||
const { events, lv, reservierbarMap, reset } = useEventLoader(rangeInterval, props.getPromiseFunc);
|
||||
|
||||
Vue.watch(lv, newValue => {
|
||||
context.emit('update:lv', newValue);
|
||||
@@ -137,10 +163,15 @@ export default {
|
||||
|
||||
const { renderers } = useRenderers();
|
||||
|
||||
Vue.watch(reservierbarMap, newVal => {
|
||||
context.emit('update:reservierbarMap', newVal);
|
||||
});
|
||||
|
||||
return {
|
||||
rangeInterval,
|
||||
events,
|
||||
lv,
|
||||
reservierbarMap,
|
||||
reset,
|
||||
renderers
|
||||
};
|
||||
@@ -162,6 +193,9 @@ export default {
|
||||
:events="events || []"
|
||||
:backgrounds="backgrounds"
|
||||
:time-grid="teachingunits"
|
||||
:reservierbar-map="reservierbarMap"
|
||||
:isReservierbar="isReservierbar"
|
||||
:create-context="createContext"
|
||||
show-btns
|
||||
@update:date="(newDate, newMode) => $emit('update:date', newDate, newMode)"
|
||||
@update:mode="(newMode, newDate) => $emit('update:mode', newMode, newDate)"
|
||||
@@ -184,6 +218,7 @@ export default {
|
||||
v-if="mode == 'event'"
|
||||
:is="renderers[event.type]?.modalContent"
|
||||
:event="event"
|
||||
@create-event="(event) => $emit('create-event', event)"
|
||||
></component>
|
||||
<component
|
||||
v-else-if="mode == 'eventheader'"
|
||||
@@ -194,6 +229,7 @@ export default {
|
||||
v-else
|
||||
:is="renderers[event.type]?.calendarEvent"
|
||||
:event="event"
|
||||
@delete-event="(event) => $emit('delete-event', event)"
|
||||
:timeSlotDisplayBehavior="
|
||||
$props.mode.toLowerCase() === 'list' ? 'always' : 'default'
|
||||
"
|
||||
|
||||
@@ -16,7 +16,19 @@ export default {
|
||||
inject: {
|
||||
timeGrid: "timeGrid",
|
||||
originalEvents: "events",
|
||||
timezone: "timezone"
|
||||
timezone: "timezone",
|
||||
reservierbar: {
|
||||
from: "isReservierbar",
|
||||
default: false
|
||||
},
|
||||
reservierbarMap: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
createContext: {
|
||||
from: 'createContext',
|
||||
default: () => {}
|
||||
},
|
||||
},
|
||||
props: {
|
||||
day: {
|
||||
@@ -103,6 +115,27 @@ export default {
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (evt.detail.source == 'slot')
|
||||
{
|
||||
if (!this.reservierbar)
|
||||
return;
|
||||
|
||||
const { date, part } = evt.detail.value || {};
|
||||
if (!date)
|
||||
return;
|
||||
let reservierbar = this.reservierbarMap?.[date.toISODate()] === true;
|
||||
if (!reservierbar)
|
||||
return;
|
||||
|
||||
this.$emit('requestModalOpen', {
|
||||
event: {
|
||||
type: this.createContext?.scope ?? 'slot',
|
||||
start: date.plus(part.start || part),
|
||||
end: date.plus(part.end || part.plus({ hours: 1 })),
|
||||
createContext: this.createContext
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
setup() {
|
||||
|
||||
@@ -7,6 +7,14 @@ export default {
|
||||
BaseSlider,
|
||||
WeekView
|
||||
},
|
||||
inject: {
|
||||
reservierbar: "isReservierbar",
|
||||
reservierbarMap: "reservierbarMap",
|
||||
createContext: {
|
||||
from: 'createContext',
|
||||
default: () => {}
|
||||
},
|
||||
},
|
||||
props: {
|
||||
currentDate: {
|
||||
type: luxon.DateTime,
|
||||
@@ -83,14 +91,33 @@ export default {
|
||||
},
|
||||
handleClickDefaults(evt) {
|
||||
switch (evt.detail.source) {
|
||||
case 'day':
|
||||
// default: Set current-date
|
||||
this.$emit('update:currentDate', evt.detail.value);
|
||||
break;
|
||||
case 'event':
|
||||
// default: Request Modal
|
||||
this.$emit('requestModalOpen', { event: evt.detail.value });
|
||||
break;
|
||||
case 'day':
|
||||
// default: Set current-date
|
||||
this.$emit('update:currentDate', evt.detail.value);
|
||||
break;
|
||||
case 'event':
|
||||
// default: Request Modal
|
||||
this.$emit('requestModalOpen', { event: evt.detail.value });
|
||||
break;
|
||||
case 'slot':
|
||||
{
|
||||
const { date, part } = evt.detail.value || {};
|
||||
if (!date)
|
||||
return;
|
||||
let reservierbar = this.reservierbarMap?.[date.toISODate()] === true;
|
||||
if (!reservierbar)
|
||||
return;
|
||||
|
||||
this.$emit('requestModalOpen', {
|
||||
event: {
|
||||
type: this.createContext?.scope ?? 'slot',
|
||||
start: date.plus(part.start || part),
|
||||
end: date.plus(part.end || part.plus({ hours: 1 })),
|
||||
createContext: this.createContext
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -522,41 +522,20 @@ export const AbgabetoolAssistenz = {
|
||||
const table = this.$refs.abgabeTable.tabulator
|
||||
|
||||
this.tableBuiltResolve()
|
||||
|
||||
table.on("columnMoved", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("columnResized", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("columnVisibilityChanged", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("filterChanged", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("headerFilterChanged", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("dataSorted", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("columnSorted", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("sortersChanged", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
const saved = this.loadState();
|
||||
|
||||
// setup change eventlisteners
|
||||
const events = [
|
||||
"columnMoved", "columnResized", "columnVisibilityChanged",
|
||||
"filterChanged", "headerFilterChanged", "dataSorted",
|
||||
"columnSorted", "sortersChanged"
|
||||
];
|
||||
|
||||
events.forEach(eventName => {
|
||||
table.on(eventName, () => this.saveState(table));
|
||||
});
|
||||
|
||||
table.on("renderComplete", () => {
|
||||
if(!this.stateRestored) {
|
||||
|
||||
@@ -999,7 +978,6 @@ export const AbgabetoolAssistenz = {
|
||||
this.tableData = this.mapProjekteToTableData(this.projektarbeiten)
|
||||
|
||||
await this.tableBuiltPromise
|
||||
|
||||
this.$refs.abgabeTable.tabulator.setData(this.tableData);
|
||||
},
|
||||
loadProjektarbeiten(all = false, callback) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
|
||||
export default {
|
||||
name: 'LvMenu',
|
||||
props:{
|
||||
menu:{
|
||||
type:Array,
|
||||
|
||||
@@ -4,7 +4,7 @@ import LvMenu from "./LvMenu.js";
|
||||
import ApiAddons from '../../../api/factory/addons.js';
|
||||
|
||||
export default {
|
||||
|
||||
name: 'LvUebersicht',
|
||||
props:{
|
||||
event:{
|
||||
type:Object,
|
||||
|
||||
@@ -1,25 +1,37 @@
|
||||
import MylvSemester from "./Semester.js";
|
||||
import Phrasen from "../../../mixins/Phrasen.js";
|
||||
import MylvSemesterCards from "./Semester.js";
|
||||
import MylvTable from "./Table.js";
|
||||
import ApiAddons from "../../../api/factory/addons.js"
|
||||
|
||||
// TODO(chris): phrase: global/studiensemester_auswaehlen
|
||||
// TODO(chris): phrase: next & prev +aria-label
|
||||
|
||||
export default {
|
||||
name: 'MyLv',
|
||||
components: {
|
||||
MylvSemester
|
||||
MylvSemesterCards,
|
||||
MylvTable
|
||||
},
|
||||
mixins: [
|
||||
Phrasen
|
||||
],
|
||||
data: () => {
|
||||
return {
|
||||
firstLoad: true,
|
||||
studiensemester: null,
|
||||
lvs: {},
|
||||
currentSemester: null
|
||||
currentSemester: null,
|
||||
mode: localStorage.getItem('myLvaDefaultMode') ?? 'cards'
|
||||
};
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
type: Vue.computed(() => this.type),
|
||||
}
|
||||
},
|
||||
inject: ['isStudent', 'isMitarbeiter'],
|
||||
computed: {
|
||||
type() {
|
||||
if(this.isStudent) return 'student'
|
||||
if(this.isMitarbeiter) return 'employee'
|
||||
return null
|
||||
},
|
||||
ready() {
|
||||
return this.studiensemester !== null && (!this.firstLoad || this.current.lvs !== null);
|
||||
},
|
||||
@@ -34,7 +46,22 @@ export default {
|
||||
axios.get(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/components/Cis/Mylv/Lvs/' + this.currentSemester).then(res => {
|
||||
this.lvs[this.currentSemester].lvs = res.data.retval || [];
|
||||
this.firstLoad = false;
|
||||
});
|
||||
|
||||
this.lvs[this.currentSemester].lvs.forEach(lv=>{
|
||||
|
||||
this.$api.call(ApiAddons.getLvMenu(lv.lehrveranstaltung_id, this.currentSemester)).then(res => {
|
||||
if(res.data) {
|
||||
|
||||
const lvProp = this.lvs[this.currentSemester].lvs.find(lv2 => lv2.lehrveranstaltung_id == lv.lehrveranstaltung_id)
|
||||
lvProp.menu = res.data
|
||||
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
return this.lvs[this.currentSemester];
|
||||
},
|
||||
@@ -67,6 +94,10 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickMode(evt, mode) {
|
||||
localStorage.setItem('myLvaDefaultMode', mode)
|
||||
this.mode = mode
|
||||
},
|
||||
prevSem() {
|
||||
this.$refs.studiensemester.selectedIndex--;
|
||||
this.$refs.studiensemester.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
@@ -99,7 +130,7 @@ export default {
|
||||
<div>
|
||||
<h2>{{$p.t('lehre/myLV')}}</h2>
|
||||
<hr>
|
||||
<div class="mylv-student" v-if="ready">
|
||||
<div class="mylv" v-if="ready">
|
||||
<div v-if="currentSemester" class="row justify-content-center mb-3">
|
||||
<div class="col-auto d-none">
|
||||
<label class="col-form-label">{{$p.t('lehre/studiensemester')}}</label>
|
||||
@@ -117,14 +148,35 @@ export default {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" col-auto my-lva-modes">
|
||||
<div class="d-flex gap-1 justify-content-end" role="group">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-secondary"
|
||||
:class="{active: mode === 'cards'}"
|
||||
@click="clickMode($event, 'cards')"
|
||||
>
|
||||
<i class="fa fa-grip"></i>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-secondary"
|
||||
:class="{active: mode === 'table'}"
|
||||
@click="clickMode($event, 'table')"
|
||||
>
|
||||
<i class="fa fa-table"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-danger" role="alert" v-else>
|
||||
{{$p.t('lehre/noLvFound')}}
|
||||
</div>
|
||||
<mylv-semester v-bind="current"/>
|
||||
<mylv-semester-cards v-if="mode == 'cards'" v-bind="current"/>
|
||||
<mylv-table v-else-if="mode == 'table'" v-bind="current"/>
|
||||
</div>
|
||||
<div class="mylv-student text-center" v-else>
|
||||
<div class="mylv text-center" v-else>
|
||||
<i class="fa-solid fa-spinner fa-pulse fa-3x"></i>
|
||||
</div>
|
||||
</div>`
|
||||
};
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
import FhcCalendar from "../../Calendar/LvPlan.js";
|
||||
|
||||
import ApiLvPlan from '../../../api/factory/lvPlan.js';
|
||||
import ApiRoomPlan from '../../../api/factory/calendar/roomPlan.js';
|
||||
|
||||
export const DEFAULT_MODE_RAUMINFO_MOBILE = 'List';
|
||||
export const DEFAULT_MODE_RAUMINFO_DESKTOP = 'Week';
|
||||
@@ -24,6 +25,36 @@ export default {
|
||||
return this.propsViewData?.mode || defaultMode;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
filteredGroups: [],
|
||||
abortController: null,
|
||||
createContext: {
|
||||
scope: 'slot_room',
|
||||
show_all_fields: false,
|
||||
room_create_information: {
|
||||
semester: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||
verband: ['A', 'B', 'C', 'D', 'E', 'F', 'V'],
|
||||
gruppe: [1, 2, 3, 4],
|
||||
studiengaenge: [],
|
||||
searchGroup: this.searchGroup,
|
||||
searchLektor: this.searchLektor,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
this.$api.call(ApiRoomPlan.getRoomCreationInfo())
|
||||
.then(result => result.data)
|
||||
.then(result => {
|
||||
if (result.berechtigt)
|
||||
{
|
||||
this.createContext.room_create_information.studiengaenge = result.studiengaenge
|
||||
}
|
||||
this.createContext.show_all_fields = result.berechtigt;
|
||||
});
|
||||
},
|
||||
methods:{
|
||||
handleChangeDate(day, newMode) {
|
||||
return this.handleChangeMode(newMode, day);
|
||||
@@ -41,8 +72,81 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
async handleCreateEvent(event)
|
||||
{
|
||||
event.ort_kurzbz = this.propsViewData.ort_kurzbz;
|
||||
this.$api.call(ApiRoomPlan.addRoomReservation(event));
|
||||
this.$refs.calendar.resetEventLoader();
|
||||
this.$refs.calendar.closeModal();
|
||||
},
|
||||
async handleDeleteEvent(event)
|
||||
{
|
||||
if (event.type !== 'reservierung')
|
||||
return;
|
||||
|
||||
if (luxon.DateTime.fromISO(`${event.datum}T${event.beginn}`) < luxon.DateTime.now())
|
||||
return;
|
||||
|
||||
this.$api.call(ApiRoomPlan.deleteRoomReservation(event.reservierung_id));
|
||||
|
||||
this.$refs.calendar.reset();
|
||||
|
||||
},
|
||||
async searchGroup(event)
|
||||
{
|
||||
const query = event.query.trim();
|
||||
|
||||
if (query.length < 2)
|
||||
return [];
|
||||
|
||||
if (this.abortController)
|
||||
this.abortController.abort();
|
||||
|
||||
this.abortController = new AbortController();
|
||||
const signal = this.abortController.signal;
|
||||
|
||||
return this.$api.call(ApiRoomPlan.getGruppen(query), { signal })
|
||||
.then(result => {
|
||||
return result.data.map(gruppe => ({
|
||||
label: gruppe.bezeichnung
|
||||
? `${gruppe.gruppe_kurzbz.trim()} (${gruppe.bezeichnung})`
|
||||
: gruppe.gruppe_kurzbz.trim(),
|
||||
gid: gruppe.gid,
|
||||
gruppe_kurzbz: gruppe.gruppe_kurzbz.trim(),
|
||||
lehrverband: gruppe.lehrverband,
|
||||
})
|
||||
);
|
||||
})
|
||||
.catch((e)=> {
|
||||
this.$fhcAlert.handleSystemError(e)
|
||||
return []
|
||||
})
|
||||
},
|
||||
async searchLektor(event)
|
||||
{
|
||||
const query = event.query.trim();
|
||||
|
||||
if (query.length < 2)
|
||||
return [];
|
||||
|
||||
if (this.abortController)
|
||||
this.abortController.abort();
|
||||
|
||||
this.abortController = new AbortController();
|
||||
const signal = this.abortController.signal;
|
||||
|
||||
return this.$api.call(ApiRoomPlan.getLektor(query), { signal })
|
||||
.then(result => {
|
||||
return result.data.map(lektor => ({
|
||||
label: `${lektor.nachname} ${lektor.vorname} (${lektor.uid})`,
|
||||
uid: lektor.uid
|
||||
})
|
||||
)})
|
||||
.catch(this.$fhcAlert.handleSystemError)
|
||||
},
|
||||
getPromiseFunc(start, end) {
|
||||
return [
|
||||
this.$api.call(ApiRoomPlan.getReservableMap(this.propsViewData.ort_kurzbz, start.toISODate(), end.toISODate())),
|
||||
this.$api.call(ApiLvPlan.getRoomInfo(this.propsViewData.ort_kurzbz, start.toISODate(), end.toISODate())),
|
||||
this.$api.call(ApiLvPlan.getOrtReservierungen(this.propsViewData.ort_kurzbz, start.toISODate(), end.toISODate()))
|
||||
];
|
||||
@@ -57,8 +161,12 @@ export default {
|
||||
:get-promise-func="getPromiseFunc"
|
||||
:date="currentDay"
|
||||
:mode="currentMode"
|
||||
:reservierbar="true"
|
||||
:create-context="createContext"
|
||||
@update:date="handleChangeDate"
|
||||
@update:mode="handleChangeMode"
|
||||
@create-event="handleCreateEvent"
|
||||
@delete-event="handleDeleteEvent"
|
||||
class="responsive-calendar"
|
||||
></fhc-calendar>
|
||||
</div>`
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import MylvSemesterStudiengang from "./Semester/Studiengang.js";
|
||||
|
||||
export default {
|
||||
name: 'Semester',
|
||||
components: {
|
||||
MylvSemesterStudiengang
|
||||
},
|
||||
@@ -43,4 +44,4 @@ export default {
|
||||
<div class="mylv-semester text-center" v-else>
|
||||
<i class="fa-solid fa-spinner fa-pulse fa-3x"></i>
|
||||
</div>`
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,7 +2,10 @@ import MylvSemesterStudiengangLv from "./Studiengang/Lv.js";
|
||||
import MylvSemesterStudiengangAverageGrade from "./Studiengang/AverageGrade.js";
|
||||
import Phrasen from "../../../../mixins/Phrasen.js";
|
||||
|
||||
import ApiAuthinfo from '../../../../api/factory/authinfo.js';
|
||||
|
||||
export default {
|
||||
name: 'Studiengang',
|
||||
components: {
|
||||
MylvSemesterStudiengangLv,
|
||||
MylvSemesterStudiengangAverageGrade
|
||||
@@ -18,6 +21,11 @@ export default {
|
||||
lvs: Array,
|
||||
sg_bezeichnung_eng: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isAverageGradeDisplayed: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
lehrveranstaltungen() {
|
||||
return [... new Map(
|
||||
@@ -33,9 +41,17 @@ export default {
|
||||
note(lv) {
|
||||
return lv.benotung ? lv.znote || lv.lvnote || null : null;
|
||||
},
|
||||
async checkIfAverageGradeIsDisplayed() {
|
||||
const authInfoResponse = await this.$api.call(ApiAuthinfo.getAuthInfo());
|
||||
const authInfo = authInfoResponse.data;
|
||||
this.isAverageGradeDisplayed = !!authInfo.isStudent;
|
||||
},
|
||||
},
|
||||
template: `<div class="card mb-3">
|
||||
|
||||
created() {
|
||||
this.checkIfAverageGradeIsDisplayed();
|
||||
},
|
||||
template: `
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title mb-3">{{$p.user_language.value === 'English' ? sg_bezeichnung_eng : bezeichnung}} - {{kuerzel}}
|
||||
<small>{{semester}}.{{$p.t('lehre/semester')}}</small>
|
||||
@@ -45,7 +61,7 @@ export default {
|
||||
<mylv-semester-studiengang-lv v-bind="lv" class="text-center h-100"></mylv-semester-studiengang-lv>
|
||||
</div>
|
||||
</div>
|
||||
<mylv-semester-studiengang-average-grade :semesterInfo="$props.semesterInfo" />
|
||||
<mylv-semester-studiengang-average-grade v-if="isAverageGradeDisplayed" :semesterInfo="$props.semesterInfo" />
|
||||
</div>
|
||||
</div>`
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import LvPruefungen from "./Lv/Pruefungen.js";
|
||||
import LvInfo from "./Lv/Info.js";
|
||||
import Phrasen from "../../../../../mixins/Phrasen.js";
|
||||
import LvUebersicht from "../../LvUebersicht.js";
|
||||
|
||||
import ApiLehre from '../../../../../api/factory/lehre.js';
|
||||
import ApiAddons from '../../../../../api/factory/addons.js';
|
||||
@@ -9,15 +6,11 @@ import ApiAddons from '../../../../../api/factory/addons.js';
|
||||
// TODO(chris): L10n
|
||||
|
||||
export default {
|
||||
components:{
|
||||
LvUebersicht,
|
||||
},
|
||||
mixins: [
|
||||
Phrasen
|
||||
],
|
||||
inject: ['studien_semester'],
|
||||
name: 'Lv',
|
||||
inject: ['studien_semester', 'type'],
|
||||
props: {
|
||||
lehrveranstaltung_id: Number,
|
||||
lehrveranstaltung_id: [Number, String],
|
||||
semesterstunden: [Number, String],
|
||||
bezeichnung: String,
|
||||
bezeichnung_eng: String,
|
||||
module: String,
|
||||
@@ -35,7 +28,8 @@ export default {
|
||||
ects: String,
|
||||
incoming: Number,
|
||||
positiv: Boolean,
|
||||
note_index: String
|
||||
note_index: String,
|
||||
menu: [Array, String]
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
@@ -46,7 +40,6 @@ export default {
|
||||
return {
|
||||
pruefungenData: null,
|
||||
info: null,
|
||||
menu: null,
|
||||
preselectedMenuItem: null,
|
||||
}
|
||||
},
|
||||
@@ -70,12 +63,6 @@ export default {
|
||||
emptyMenu(){
|
||||
return !this.menu || !Array.isArray(this.menu) || Array.isArray(this.menu) && this.menu.length == 0;
|
||||
},
|
||||
bodyStyle() {return {};
|
||||
/*const bodyStyle = {};
|
||||
if (this.farbe)
|
||||
bodyStyle['background-color'] = '#' + this.farbe;
|
||||
return bodyStyle;*/
|
||||
},
|
||||
grade() {
|
||||
const languageIndex = this.$p.user_language.value === 'English' ? 1 : 0
|
||||
// no more showing of grade LV, if grade Zeugnis is not existing yet
|
||||
@@ -89,7 +76,6 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
||||
fetchMenu(lehrveranstaltung_id = this.lehrveranstaltung_id, studien_semester = this.studien_semester) {
|
||||
return this.$api
|
||||
.call(ApiAddons.getLvMenu(lehrveranstaltung_id, studien_semester))
|
||||
@@ -101,28 +87,18 @@ export default {
|
||||
this.menu = [];
|
||||
});
|
||||
},
|
||||
|
||||
c4_target(menuItem) {
|
||||
if (menuItem.c4_moodle_links?.length > 0) return null;
|
||||
return menuItem.c4_target ?? null;
|
||||
},
|
||||
c4_link(menuItem) {
|
||||
if (!menuItem) return null;
|
||||
if (Array.isArray(menuItem.c4_moodle_links) && menuItem.c4_moodle_links.length) {
|
||||
return '#';
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return menuItem.c4_link ?? null;
|
||||
}
|
||||
},
|
||||
openLvOption(menuItem){
|
||||
if (menuItem.id == "core_menu_mailanstudierende"){
|
||||
window.location.href = menuItem.c4_link;
|
||||
} else if (menuItem.id == "core_menu_digitale_anwesenheitslisten") {
|
||||
window.location.href = menuItem.c4_link;
|
||||
} else{
|
||||
this.preselectedMenuItem = menuItem;
|
||||
Vue.nextTick(() => {
|
||||
this.$refs.lvUebersicht.show();
|
||||
});
|
||||
}
|
||||
},
|
||||
openPruefungen() {
|
||||
if (!this.LvHasPruefungenInformation) return;
|
||||
|
||||
@@ -130,75 +106,65 @@ export default {
|
||||
pruefungenData: this.pruefungenData,
|
||||
bezeichnung: this.bezeichnung
|
||||
});
|
||||
},
|
||||
openInfos() {
|
||||
if (!this.info) {
|
||||
this.info = true;
|
||||
// TODO(chris): load all this params on ajax?
|
||||
LvInfo.popup({
|
||||
lehrveranstaltung_id: this.lehrveranstaltung_id,
|
||||
bezeichnung: this.bezeichnung,
|
||||
bezeichnung_eng: this.bezeichnung_eng,
|
||||
studiengang_kuerzel: this.studiengang_kuerzel,
|
||||
semester: this.semester,
|
||||
studien_semester: this.studien_semester,
|
||||
orgform_kurzbz: this.orgform_kurzbz,
|
||||
sprache: this.sprache,
|
||||
ects: this.ects,
|
||||
incoming: this.incoming
|
||||
}).then(() => this.info = false).catch(() => this.info = false);
|
||||
}
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
studien_semester(newValue){
|
||||
this.fetchMenu(this.lehrveranstaltung_id, newValue);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$api
|
||||
.call(ApiLehre.getStudentPruefungen(this.lehrveranstaltung_id))
|
||||
.then(res => res.data)
|
||||
.then(pruefungen => {
|
||||
this.pruefungenData = pruefungen;
|
||||
});
|
||||
if(this.type == 'student') {
|
||||
this.$api
|
||||
.call(ApiLehre.getStudentPruefungen(this.lehrveranstaltung_id))
|
||||
.then(res => res.data)
|
||||
.then(pruefungen => {
|
||||
this.pruefungenData = pruefungen;
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.fetchMenu(this.lehrveranstaltung_id, this.studien_semester);
|
||||
},
|
||||
template: /*html*/`<div class="mylv-semester-studiengang-lv card">
|
||||
<lv-uebersicht ref="lvUebersicht" :preselectedMenu="preselectedMenuItem" :event="{
|
||||
lehrveranstaltung_id: lehrveranstaltung_id,
|
||||
studiensemester_kurzbz:studien_semester,
|
||||
lehrfach_bez:studien_semester,
|
||||
stg_kurzbzlang:studien_semester,
|
||||
}"/>
|
||||
|
||||
template: /*html*/`
|
||||
<div class="mylv-semester-studiengang-lv card">
|
||||
<div class="p-2" :class="is_organisatorische_einheit?'':'card-header'">
|
||||
<!-- {{module}} if the module of the lv is important then query the module from the api endpoint for LV-->
|
||||
<h6 class="fw-bold" v-if="is_organisatorische_einheit" >{{ $p.t('lehre/organisationseinheit') }}:</h6>
|
||||
<h6 class="mb-0">{{$p.user_language.value === 'English' ? bezeichnung_eng : bezeichnung}}</h6>
|
||||
</div>
|
||||
<div v-if="!emptyMenu" class="card-body " :style="bodyStyle">
|
||||
<div v-if="!emptyMenu" class="card-body ">
|
||||
<template v-if="menu">
|
||||
<ul class="list-group border-top-0 border-bottom-0 rounded-0">
|
||||
<li :type="menuItem.c4_link ? 'button' : null" v-for="menuItem in menu" class="list-group-item border-0 " >
|
||||
<div class="d-flex flex-row" :data-bs-toggle="menuItem.c4_moodle_links?.length ? 'dropdown' : null">
|
||||
<li :type="menuItem.c4_link ? 'button' : null"
|
||||
v-for="(menuItem, index) in menu" :key="index" class="list-group-item border-0 " >
|
||||
<div class="d-flex flex-row">
|
||||
<div class="mx-4">
|
||||
<i :class="[menuItem.c4_icon2 ? menuItem.c4_icon2 : 'fa-solid fa-pen-to-square', !menuItem.c4_link ? 'unavailable' : null ]"></i>
|
||||
</div>
|
||||
<a
|
||||
<a :id="menuItem.name"
|
||||
class="fhc-body text-decoration-none text-truncate"
|
||||
:id="'moodle_links_'+lehrveranstaltung_id"
|
||||
:class="{ 'unavailable':!menuItem.c4_link, 'dropdown-toggle':menuItem.c4_moodle_links?.length }"
|
||||
:class="{ 'unavailable':!menuItem.c4_link }"
|
||||
:target="menuItem.c4_target"
|
||||
:href="c4_link(menuItem) ? c4_link(menuItem) : null">
|
||||
{{ menuItem.phrase ? $p.t(menuItem.phrase) : menuItem.name}}
|
||||
</a>
|
||||
|
||||
<div v-if="(menuItem.c4_moodle_links?.length || menuItem.c4_linkList?.length) && menuItem.c4_link" class="dropdown">
|
||||
<button
|
||||
class="btn btn-sm dropdown-toggle dropdown-toggle-split border-0"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
<span class="visually-hidden">Toggle Dropdown</span>
|
||||
</button>
|
||||
|
||||
<ul v-if="menuItem.c4_moodle_links?.length" class="dropdown-menu dropdown-menu p-0">
|
||||
<li v-for="item in menuItem.c4_moodle_links" :key="item.url">
|
||||
<a class="dropdown-item border-bottom" :href="item.url" target="#">{{ item.lehrform }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul v-else class="dropdown-menu dropdown-menu p-0">
|
||||
<li v-for="([text, link], i) in menuItem.c4_linkList" :key="i">
|
||||
<a class="dropdown-item border-bottom" :href="link" target="#">{{ text }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<ul v-if="menuItem.c4_moodle_links?.length" class="dropdown-menu p-0" :aria-labelledby="'moodle_links_'+lehrveranstaltung_id">
|
||||
<li v-for="item in menuItem.c4_moodle_links"><a class="dropdown-item border-bottom" :href="item.url">{{item.lehrform}}</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
@@ -208,16 +174,31 @@ export default {
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div v-if="!emptyMenu" class="card-footer">
|
||||
<div
|
||||
@click.prevent="openPruefungen()"
|
||||
:type="LvHasPruefungenInformation ? 'button' : ''"
|
||||
class="d-flex flex-row align-items-center gap-1"
|
||||
>
|
||||
<i class="fa fa-check text-success" v-if="positiv"></i>
|
||||
<span :style="'color:'+gradeColor">{{ grade || $p.t('lehre/noGrades') }}</span>
|
||||
<i v-if="LvHasPruefungenInformation" class="fa fa-circle-info ms-1"></i>
|
||||
<div v-if="!emptyMenu && type == 'student'" class="card-footer">
|
||||
<div class="row">
|
||||
<!-- template for the LV if there are multiple pruefungen -->
|
||||
<template v-if="LvHasPruefungenInformation">
|
||||
<a href="#" class="col-auto text-start text-decoration-none" @click.prevent="openPruefungen">
|
||||
<i class="fa fa-check text-success" v-if="positiv"></i>
|
||||
<span class="ps-1" :style="'color:'+gradeColor">{{ grade || $p.t('lehre/noGrades') }}</span>
|
||||
<i class="fa fa-circle-info ms-1"></i>
|
||||
</a>
|
||||
</template>
|
||||
<!-- template for the LV with no pruefungen -->
|
||||
<template v-else>
|
||||
<span class="col-auto text-start text-decoration-none" >
|
||||
<i class="fa fa-check text-success" v-if="positiv"></i>
|
||||
<span class="ps-1" :style="'color:'+gradeColor">{{ grade || $p.t('lehre/noGrades') }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="!emptyMenu && type == 'employee'" class="card-footer">
|
||||
<div class="row">
|
||||
<div class="col-auto">
|
||||
<span class="ps-1">{{ $p.t('lehre/semesterstunden') }}: {{ semesterstunden }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,345 @@
|
||||
import {CoreFilterCmpt} from "../../../components/filter/Filter.js";
|
||||
|
||||
export default {
|
||||
name: 'MylvTable',
|
||||
components: {
|
||||
CoreFilterCmpt
|
||||
},
|
||||
props: {
|
||||
semester: [String],
|
||||
lvs: Array,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
phrasenPromise: null,
|
||||
phrasenResolved: false,
|
||||
tabulatorUuid: null,
|
||||
tableBuiltResolve: null,
|
||||
tableBuiltPromise: null,
|
||||
mylvTableOptions: {
|
||||
height: Vue.ref(400),
|
||||
index: 'lehrveranstaltung_id',
|
||||
layout: 'fitDataStretch',
|
||||
placeholder: this.$p.t('global/noDataAvailable'),
|
||||
columns: [
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('lehre/studiengang'))), field: 'sg_bezeichnung', widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('global/bezeichnung'))), field: 'bezeichnung', widthGrow: 2},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('lehre/orgform'))), field: 'orgform_kurzbz', widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('lehre/kurzbz'))), field: 'studiengang_kuerzel', widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('lehre/semesterstunden'))), field: 'semesterstunden',
|
||||
bottomCalc: this.semesterstundenCalc, widthGrow: 1, visible: false},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('global/actions'))), headerSort: false,
|
||||
field: 'menu', formatter: this.actionFormatter, widthGrow: 1, tooltip: this.spoofingFunc}
|
||||
],
|
||||
persistence: false,
|
||||
persistenceID: "mylv_2026_04_17"
|
||||
},
|
||||
mylvTableEventHandlers: [
|
||||
|
||||
]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
ready() { return this.lvs !== null; },
|
||||
},
|
||||
methods: {
|
||||
semesterstundenCalc(values, data) {
|
||||
let sum = 0
|
||||
values.forEach(val => {
|
||||
sum += Number(val)
|
||||
})
|
||||
return sum
|
||||
},
|
||||
spoofingFunc() {
|
||||
// intentionally send empty tooltip info so tabulator tooltip doesnt get rendered but hover event propagates
|
||||
// to individual button tooltips
|
||||
return ''
|
||||
},
|
||||
c4_link(menuItem) {
|
||||
if (!menuItem) return null;
|
||||
if (Array.isArray(menuItem.c4_moodle_links) && menuItem.c4_moodle_links.length) {
|
||||
return '#';
|
||||
} else {
|
||||
return menuItem.c4_link ?? null;
|
||||
}
|
||||
},
|
||||
handleUuidDefined(uuid) {
|
||||
this.tabulatorUuid = uuid
|
||||
},
|
||||
tableResolve(resolve) {
|
||||
this.tableBuiltResolve = resolve
|
||||
},
|
||||
actionFormatter(cell) {
|
||||
let container = document.createElement('div');
|
||||
container.className = "d-flex gap-2";
|
||||
|
||||
const data = cell.getData()
|
||||
if(data.menu && data.menu.length) {
|
||||
|
||||
container.className = "d-flex flex-wrap gap-2"
|
||||
|
||||
data.menu.forEach((lvLink) => {
|
||||
// render dropdown if we have a link and some some linklist
|
||||
const hasDropdown = (lvLink.c4_moodle_links?.length || lvLink.c4_linkList?.length) && lvLink.c4_link;
|
||||
|
||||
if (hasDropdown) {
|
||||
// button group
|
||||
const group = document.createElement('div');
|
||||
group.className = 'btn-group';
|
||||
|
||||
// main action button
|
||||
const button= this.createActionButton(lvLink)
|
||||
|
||||
// toggle button
|
||||
const toggle = document.createElement('button');
|
||||
toggle.className = 'btn btn-sm dropdown-toggle dropdown-toggle-split border-0';
|
||||
toggle.type = 'button';
|
||||
toggle.dataset.bsToggle = 'dropdown'; // uses absolute position which gets clipped by tabulator
|
||||
toggle.ariaExpanded = 'false';
|
||||
toggle.innerHTML = '<span class="visually-hidden">Toggle Dropdown</span>';
|
||||
|
||||
// dropdown menu
|
||||
const dropMenu = document.createElement('ul');
|
||||
dropMenu.className = 'dropdown-menu dropdown-menu p-0';
|
||||
|
||||
// moodle links have priority to be dropdown items but both can be!
|
||||
const items = lvLink.c4_moodle_links?.length
|
||||
? lvLink.c4_moodle_links.map(item => ({ text: item.lehrform, href: item.url }))
|
||||
: lvLink.c4_linkList.map(([text, link]) => ({ text, href: link }));
|
||||
|
||||
|
||||
items.forEach(({ text, href }) => {
|
||||
const li = document.createElement('li');
|
||||
const a = document.createElement('a');
|
||||
a.className = 'dropdown-item border-bottom';
|
||||
a.href = href;
|
||||
a.target = '#';
|
||||
a.textContent = text;
|
||||
li.appendChild(a);
|
||||
dropMenu.appendChild(li);
|
||||
});
|
||||
|
||||
group.appendChild(button);
|
||||
group.appendChild(toggle);
|
||||
group.appendChild(dropMenu);
|
||||
container.appendChild(group);
|
||||
|
||||
} else {
|
||||
container.appendChild(this.createActionButton(lvLink));
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
return container;
|
||||
},
|
||||
createActionButton(lvLink){
|
||||
const button = document.createElement('a');
|
||||
button.className = 'fhc-body text-decoration-none text-truncate';
|
||||
if (!lvLink.c4_link) button.classList.add('unavailable');
|
||||
button.id = `${lvLink.name}_${lvLink.lehrveranstaltung_id}`;
|
||||
|
||||
const icon = lvLink.c4_icon2 ?? 'fa-solid fa-pen-to-square';
|
||||
const label = lvLink.phrase ? this.$p.t(lvLink.phrase) : lvLink.name;
|
||||
button.title = label;
|
||||
button.innerHTML = `<i class="${icon}"></i><span style="margin-left:2px;">${label}</span>`;
|
||||
|
||||
button.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
const url = this.c4_link(lvLink);
|
||||
if (url) {
|
||||
const target = lvLink.c4_target || '_blank';
|
||||
if (target === '_blank') {
|
||||
window.open(url, '_blank', 'noopener,noreferrer');
|
||||
} else {
|
||||
window.location.href = url;
|
||||
}
|
||||
} else {
|
||||
console.warn("Link is unavailable for:", lvLink.name);
|
||||
}
|
||||
});
|
||||
return button
|
||||
},
|
||||
loadState() {
|
||||
return JSON.parse(localStorage.getItem(this.mylvTableOptions.persistenceID) || "null");
|
||||
},
|
||||
saveState(table) {
|
||||
// avoid storing state after first restore part happened
|
||||
if(!this.stateRestored) return
|
||||
const rawLayout = table.getColumnLayout();
|
||||
const state = {
|
||||
columns: rawLayout.map(col => ({
|
||||
field: col.field,
|
||||
visible: col.visible,
|
||||
width: col.width,
|
||||
})),
|
||||
sort: table.getSorters().map(s => ({
|
||||
field: s.field,
|
||||
dir: s.dir,
|
||||
})),
|
||||
filters: table.getFilters(),
|
||||
headerFilters: table.getHeaderFilters()
|
||||
};
|
||||
|
||||
localStorage.setItem(this.mylvTableOptions.persistenceID, JSON.stringify(state));
|
||||
},
|
||||
handleTableBuilt() {
|
||||
const table = this.$refs.mylvTable.tabulator
|
||||
|
||||
this.tableBuiltResolve()
|
||||
|
||||
table.on("columnMoved", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("columnResized", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("columnVisibilityChanged", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("filterChanged", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("headerFilterChanged", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("dataSorted", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("columnSorted", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
table.on("sortersChanged", () => {
|
||||
this.saveState(table);
|
||||
});
|
||||
|
||||
const saved = this.loadState();
|
||||
|
||||
table.on("renderComplete", () => {
|
||||
if(!this.stateRestored) {
|
||||
|
||||
if (saved?.columns && !this.colLayoutRestored) {
|
||||
const layout = saved.columns.map(col => ({
|
||||
field: col.field,
|
||||
width: col.width,
|
||||
visible: col.visible,
|
||||
// add more if needed, but keep it simple
|
||||
}));
|
||||
|
||||
table.setColumnLayout(layout);
|
||||
|
||||
this.colLayoutRestored = true;
|
||||
}
|
||||
|
||||
if (saved?.filters && !this.filtersRestored) {
|
||||
this.filtersRestored = true // instantly avoid retriggers
|
||||
table.setFilter(saved.filters);
|
||||
}
|
||||
if (saved?.headerFilters && !this.headerFiltersRestored) {
|
||||
this.headerFiltersRestored = true // instantly avoid retriggers
|
||||
for (let hf of saved.headerFilters) {
|
||||
table.setHeaderFilterValue(hf.field, hf.value);
|
||||
}
|
||||
}
|
||||
|
||||
if (saved?.sort?.length && !this.sortRestored) {
|
||||
this.sortRestored = true;
|
||||
|
||||
setTimeout(() => {
|
||||
const sortList = saved.sort.map(s => {
|
||||
const col = table.columnManager.findColumn(s.field);
|
||||
if (!col) {
|
||||
return null;
|
||||
}
|
||||
return { column: col, dir: s.dir };
|
||||
}).filter(Boolean);
|
||||
|
||||
table.setSort(sortList);
|
||||
}, 100);
|
||||
}
|
||||
this.stateRestored = true
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
},
|
||||
async setupData() {
|
||||
this.$refs.mylvTable.tabulator.setData(this.lvs);
|
||||
},
|
||||
async setupMounted() {
|
||||
this.tableBuiltPromise = new Promise(this.tableResolve)
|
||||
await this.tableBuiltPromise
|
||||
|
||||
this.setupData()
|
||||
|
||||
const tableID = this.tabulatorUuid ? ('-' + this.tabulatorUuid) : ''
|
||||
const tableDataSet = document.getElementById('filterTableDataset' + tableID);
|
||||
if(!tableDataSet) return
|
||||
const rect = tableDataSet.getBoundingClientRect();
|
||||
|
||||
const h = window.visualViewport.height - rect.top - 50
|
||||
if(this.$refs.mylvTable) {
|
||||
this.$refs.mylvTable.$refs.table.style.setProperty('height', h+'px')
|
||||
|
||||
// necessary so the wrapping action row resolves to the full rowHeight required
|
||||
// without the redraw here actions past the initial rowHeight would be clipped off
|
||||
this.$refs.mylvTable.tabulator.redraw(true)
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.phrasenPromise = this.$p.loadCategory(['global', 'lehre', 'lvinfo'])
|
||||
this.phrasenPromise.then(()=> {this.phrasenResolved = true})
|
||||
},
|
||||
mounted() {
|
||||
this.setupMounted()
|
||||
},
|
||||
watch: {
|
||||
lvs: {
|
||||
async handler(newVal) {
|
||||
await this.tableBuiltPromise;
|
||||
if(!this.$refs.mylvTable?.tabulator) return
|
||||
|
||||
this.$refs.mylvTable.tabulator.setData(newVal);
|
||||
|
||||
const tableID = this.tabulatorUuid ? ('-' + this.tabulatorUuid) : ''
|
||||
const tableDataSet = document.getElementById('filterTableDataset' + tableID);
|
||||
if(!tableDataSet) return
|
||||
const rect = tableDataSet.getBoundingClientRect();
|
||||
|
||||
const h = window.visualViewport.height - rect.top - 50
|
||||
if(this.$refs.mylvTable) {
|
||||
this.$refs.mylvTable.$refs.table.style.setProperty('height', h+'px')
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="mylv-semester-table" v-if="ready">
|
||||
<core-filter-cmpt
|
||||
v-if="phrasenResolved"
|
||||
@uuidDefined="handleUuidDefined"
|
||||
:title="''"
|
||||
ref="mylvTable"
|
||||
:tabulator-options="mylvTableOptions"
|
||||
:tabulator-events="mylvTableEventHandlers"
|
||||
@tableBuilt="handleTableBuilt"
|
||||
tableOnly
|
||||
:sideMenu="false"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="tabulatorUuid === null" class="text-center d-flex justify-content-center align-items-center h-100" >
|
||||
<i class="fa-solid fa-spinner fa-pulse fa-3x"></i>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -480,7 +480,7 @@ export default {
|
||||
<!-- START OF SIDE PANEL -->
|
||||
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
|
||||
<!-- Bearbeiten Button -->
|
||||
<div class="row d-none d-md-block ">
|
||||
<div v-if="isEditable" class="row d-none d-md-block ">
|
||||
<div class="col mb-3">
|
||||
<button @click="()=>showEditProfilModal()" type="button" class="text-start card w-100 btn btn-outline-secondary" >
|
||||
<div class="row">
|
||||
|
||||
@@ -171,8 +171,8 @@ export const Profil = {
|
||||
const data = viewDataResult.data;
|
||||
if (!data) return;
|
||||
|
||||
this.isEditable = data.editable;
|
||||
this.view = data.profil_data.view;
|
||||
this.isEditable = data.profil_data.editable;
|
||||
this.data = data.profil_data.data;
|
||||
this.calendarSyncUrls = data.calendar_sync_urls ?? [];
|
||||
this.authPermissions = data.permissions;
|
||||
|
||||
@@ -280,14 +280,14 @@ export default {
|
||||
<div class="row">
|
||||
<div class="d-md-none col-12 ">
|
||||
<!-- Bearbeiten Button -->
|
||||
<div v-if="isEditable" class="row ">
|
||||
<div class="col mb-3">
|
||||
<div v-if="isEditable" class="row">
|
||||
<div class="col mb-4">
|
||||
<button @click="showEditProfilModal" type="button" class="card text-start w-100 btn btn-outline-secondary" >
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<div class="col-auto">
|
||||
<i class="fa fa-edit"></i>
|
||||
</div>
|
||||
<div class="col-10">{{$p.t('ui','bearbeiten')}}</div>
|
||||
<div class="col-auto">{{$p.t('ui','bearbeiten')}}</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
@@ -409,7 +409,7 @@ export default {
|
||||
@tableBuilt="zutrittsgruppenTableBuilt"
|
||||
:title="$p.t('profil','zutrittsGruppen')"
|
||||
ref="zutrittsgruppenTable"
|
||||
:tabulator-options="zutrittsgruppen_table_options"
|
||||
:tabulator-options="zutrittsgruppen_table_options"
|
||||
tableOnly
|
||||
:sideMenu="false"
|
||||
noColumnFilter />
|
||||
@@ -420,14 +420,14 @@ export default {
|
||||
<!-- START OF SIDE PANEL -->
|
||||
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
|
||||
<!-- Bearbeiten Button -->
|
||||
<div class="row d-none d-md-block">
|
||||
<div v-if="isEditable" class="row d-none d-md-block">
|
||||
<div class="col mb-3">
|
||||
<button @click="()=>showEditProfilModal()" type="button" class="card text-start w-100 btn btn-outline-secondary" >
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<div class="col-auto">
|
||||
<i class="fa fa-edit"></i>
|
||||
</div>
|
||||
<div class="col-10">{{$p.t('ui','bearbeiten')}}</div>
|
||||
<div class="col-auto">{{$p.t('ui','bearbeiten')}}</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,339 @@
|
||||
import {CoreFilterCmpt} from "../../../components/filter/Filter.js";
|
||||
import ApiPaabgabe from '../../../api/factory/paabgabeUebersicht.js'
|
||||
import Loader from "../../Loader.js";
|
||||
|
||||
export const ProjektabgabeUebersicht = {
|
||||
name: "ProjektabgabeUebersicht",
|
||||
components: {
|
||||
CoreFilterCmpt,
|
||||
Loader
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
phrasenPromise: null,
|
||||
phrasenResolved: false,
|
||||
tabulatorUuid: Vue.ref(0),
|
||||
tableBuiltResolve: null,
|
||||
tableBuiltPromise: null,
|
||||
studiengaenge: null,
|
||||
abgabetypen: null,
|
||||
termine: null,
|
||||
abgaben: null,
|
||||
defaultStudiengang: {
|
||||
studiengang_kz: null,
|
||||
kuerzel: '-'
|
||||
},
|
||||
defaultTyp: {
|
||||
paabgabetyp_kurzbz: null,
|
||||
bezeichnung: '-'
|
||||
},
|
||||
defaultTermin: {
|
||||
termin: null,
|
||||
termin_anzeige: Vue.computed(() => this.$p.t('ui/alle'))
|
||||
},
|
||||
selectedStudiengang: null,
|
||||
selectedAbgabetyp: null,
|
||||
selectedTermin: null,
|
||||
personSearchString: null,
|
||||
paabgabeTableOptions: {
|
||||
height: Vue.ref(400),
|
||||
index: 'paabgabe_id',
|
||||
layout: 'fitColumns',
|
||||
//~ placeholder: this.$p.t('global/noDataAvailable'),
|
||||
columns: [
|
||||
{
|
||||
title: Vue.computed(() => this.$p.t('global/aktionen')), field: 'actions',
|
||||
formatter: (cell, formatterParams, onRendered) => {
|
||||
let container = document.createElement('div');
|
||||
container.className = "d-flex gap-2";
|
||||
|
||||
let downloadButton = document.createElement('button');
|
||||
downloadButton.className = 'btn btn-outline-secondary';
|
||||
downloadButton.innerHTML = '<i class="fa fa-download"></i>';
|
||||
downloadButton.title = this.$p.t('ui', 'downloadDok');
|
||||
downloadButton.addEventListener('click', evt => {
|
||||
evt.stopPropagation();
|
||||
this.actionDownload(cell.getData().paabgabe_id);
|
||||
});
|
||||
container.append(downloadButton);
|
||||
|
||||
if (this.showEdit)
|
||||
{
|
||||
let editButton = document.createElement('button');
|
||||
editButton.className = 'btn btn-outline-secondary';
|
||||
editButton.innerHTML = '<i class="fa fa-edit"></i>';
|
||||
//editButton.addEventListener('click', () =>
|
||||
//this.$refs.edit.open(cell.getData())
|
||||
//);
|
||||
container.append(editButton);
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
},
|
||||
{title: Vue.computed(() => this.$p.t('abgabetool/paabgabeid')), field: 'paabgabe_id', visible: false},
|
||||
{title: Vue.computed(() => this.$p.t('abgabetool/projektarbeitid')), field: 'projektarbeit_id', visible: false},
|
||||
{
|
||||
title: Vue.computed(() => this.$p.t('abgabetool/termin')),
|
||||
field: "termin",
|
||||
widthGrow: 1,
|
||||
formatter: function (cell) {
|
||||
const dateStr = cell.getValue();
|
||||
if (!dateStr) return "";
|
||||
|
||||
const date = new Date(dateStr);
|
||||
return date.toLocaleString("de-DE", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
hour12: false
|
||||
});
|
||||
}
|
||||
},
|
||||
{title: Vue.computed(() => this.$p.t('abgabetool/c4abgabetyp')), field: 'paabgabetyp_bezeichnung'},
|
||||
{title: Vue.computed(() => this.$p.t('person/uid')), field: 'uid'},
|
||||
{title: Vue.computed(() => this.$p.t('person/vorname')), field: 'vorname'},
|
||||
{title: Vue.computed(() => this.$p.t('person/nachname')), field: 'nachname'},
|
||||
{title: Vue.computed(() => this.$p.t('abgabetool/c4projekttyp')), field: 'projekttyp_kurzbz'},
|
||||
{title: Vue.computed(() => this.$p.t('abgabetool/c4titel')), field: 'titel'},
|
||||
{title: Vue.computed(() => this.$p.t('abgabetool/personStatus')), field: 'personStatus'},
|
||||
{
|
||||
title: "in Visual Library",
|
||||
field: 'in_visual_library',
|
||||
formatter: (cell) => {
|
||||
return cell.getValue() ? this.$p.t('ui/ja') : this.$p.t('ui/nein');
|
||||
}
|
||||
}
|
||||
],
|
||||
persistence: false,
|
||||
},
|
||||
paabgabeTableEventHandlers: [{
|
||||
event: "tableBuilt",
|
||||
handler: async () => {
|
||||
this.tableBuiltResolve()
|
||||
}
|
||||
}
|
||||
],
|
||||
showEdit: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
tableResolve(resolve) {
|
||||
this.tableBuiltResolve = resolve
|
||||
},
|
||||
setupData(){
|
||||
//~ const d = data.map(paabgabe => {
|
||||
//~ return {
|
||||
//~ ort_kurzbz: paabgabe.ort_kurzbz,
|
||||
//~ bezeichnung: paabgabe.bezeichnung.replace('&', '&'),
|
||||
//~ nummer: paabgabe.planbezeichnung,
|
||||
//~ personen: paabgabe.max_person
|
||||
//~ }
|
||||
//~ })
|
||||
|
||||
this.$refs.paabgabeTable.tabulator.setData(this.abgaben);
|
||||
},
|
||||
// set placeholder text for no data table
|
||||
setNoDataPlaceholder() {
|
||||
this.$refs.paabgabeTable.tabulatorOptions.placeholder = this.$p.t('global/noDataAvailable');
|
||||
},
|
||||
loadStudiengaenge() {
|
||||
this.$api.call(ApiPaabgabe.getStudiengaenge())
|
||||
.then(res => {
|
||||
this.studiengaenge = res?.data ?? []
|
||||
})
|
||||
},
|
||||
loadPaabgabeTypes() {
|
||||
this.$api.call(ApiPaabgabe.getPaAbgabetypen())
|
||||
.then(res => {
|
||||
this.abgabetypen = res?.data ?? []
|
||||
})
|
||||
},
|
||||
loadTermine() {
|
||||
this.$api.call(ApiPaabgabe.getTermine(this.selectedStudiengang, this.selectedAbgabetyp))
|
||||
.then(res => {
|
||||
this.selectedTermin = null;
|
||||
this.termine = res?.data ?? []
|
||||
})
|
||||
},
|
||||
loadPaAbgaben() {
|
||||
this.$refs.loader.show();
|
||||
|
||||
this.$api.call(
|
||||
ApiPaabgabe.getPaAbgaben(this.selectedStudiengang, this.selectedAbgabetyp, this.selectedTermin, this.personSearchString)
|
||||
)
|
||||
.then(res => {
|
||||
this.$refs.loader.hide();
|
||||
this.abgaben = res?.data ?? [];
|
||||
this.setupData(res?.data ?? []);
|
||||
});
|
||||
},
|
||||
handleUuidDefined(uuid) {
|
||||
this.tabulatorUuid = uuid
|
||||
},
|
||||
//~ setRoute(val) {
|
||||
//~ // TODO: router push
|
||||
//~ },
|
||||
async setupMounted() {
|
||||
|
||||
// load data for dropdowns
|
||||
this.loadStudiengaenge();
|
||||
this.loadPaabgabeTypes();
|
||||
this.loadTermine();
|
||||
|
||||
// wait for table to build
|
||||
this.tableBuiltPromise = new Promise(this.tableResolve);
|
||||
await this.tableBuiltPromise;
|
||||
|
||||
// data placeholder after table built so phrases are available
|
||||
this.setNoDataPlaceholder();
|
||||
//this.loadPaAbgaben();
|
||||
|
||||
|
||||
//~ const tableID = this.tabulatorUuid ? ('-' + this.tabulatorUuid) : ''
|
||||
//~ const tableDataSet = document.getElementById('filterTableDataset' + tableID);
|
||||
//~ if(!tableDataSet) return
|
||||
//~ const rect = tableDataSet.getBoundingClientRect();
|
||||
|
||||
//~ const h = window.visualViewport.height - rect.top - 100
|
||||
//~ if(this.$refs.raumsucheTable) {
|
||||
//~ this.$refs.raumsucheTable.$refs.table.style.setProperty('height', h+'px')
|
||||
//~ }
|
||||
|
||||
},
|
||||
actionDownload(paabgabe_id) {
|
||||
//~ window.open(
|
||||
//~ FHC_JS_DATA_STORAGE_OBJECT.app_root
|
||||
//~ + FHC_JS_DATA_STORAGE_OBJECT.ci_router
|
||||
//~ +'/api/frontend/v1/education/paabgabeuebersicht/downloadProjektarbeit?paabgabe_id=' + encodeURIComponent(paabgabe_id),
|
||||
//~ '_blank'
|
||||
//~ );
|
||||
},
|
||||
// download zip file with all searched submission files
|
||||
actionDownloadZip() {
|
||||
const url = new URL(FHC_JS_DATA_STORAGE_OBJECT.app_root
|
||||
+ FHC_JS_DATA_STORAGE_OBJECT.ci_router
|
||||
+'/api/frontend/v1/education/PaabgabeUebersicht/downloadZip');
|
||||
if (this.selectedStudiengang) url.searchParams.append('studiengang_kz', this.selectedStudiengang);
|
||||
if (this.selectedAbgabetyp) url.searchParams.append('abgabetyp_kurzbz', this.selectedAbgabetyp);
|
||||
if (this.selectedTermin) url.searchParams.append('abgabedatum', this.selectedTermin);
|
||||
if (this.personSearchString) url.searchParams.append('personSearchString', this.personSearchString);
|
||||
window.open(url.toString(), '_blank');
|
||||
},
|
||||
async getViewData() {
|
||||
const viewDataResponse = await this.$api.call(ApiPaabgabe.getViewData());
|
||||
const viewData = viewDataResponse.data;
|
||||
this.showEdit = viewData.showEdit;
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isDarkMode() {
|
||||
return this.$theme.theme_name.value == 'dark';
|
||||
},
|
||||
personSearchEnabled() {
|
||||
return this.selectedStudiengang == null && this.selectedTermin == null && this.selectedAbgabetyp == null;
|
||||
},
|
||||
abgabeSearchEnabled() {
|
||||
return this.personSearchString == '' || this.personSearchString == null;
|
||||
},
|
||||
zipDownloadUrl() {
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/api/frontend/v1/education/PaabgabeUebersicht/downloadZip';
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
await this.getViewData();
|
||||
this.phrasenPromise = this.$p.loadCategory(['abgabetool', 'global', 'person', 'ui']);
|
||||
this.phrasenPromise.then(()=> {this.phrasenResolved = true});
|
||||
},
|
||||
mounted() {
|
||||
this.setupMounted();
|
||||
},
|
||||
template: `
|
||||
<h1 class="h3">{{$p.t('abgabetool/projektabgabeUebersicht')}}</h1>
|
||||
<hr>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-12 col-lg-2">
|
||||
<h6>{{ $p.t('abgabetool/studiengang') }}:</h6>
|
||||
<select
|
||||
ref="studiengang"
|
||||
id="studiengangSelect"
|
||||
v-model="selectedStudiengang"
|
||||
class="form-select"
|
||||
:aria-label="$p.t('abgabetool/studiengang_auswaehlen')"
|
||||
:disabled="!abgabeSearchEnabled"
|
||||
@change="loadTermine();"
|
||||
>
|
||||
<option :key="defaultStudiengang.studiengang_kz" selected :value="defaultStudiengang.studiengang_kz">{{defaultStudiengang.kuerzel}}</option>
|
||||
<option v-for="stg in studiengaenge" :key="stg.studiengang_kz" :value="stg.studiengang_kz">{{stg.kuerzel}}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-2">
|
||||
<h6>{{ $p.t('abgabetool/c4abgabetyp') }}:</h6>
|
||||
<select
|
||||
ref="abgabetyp"
|
||||
id="abgabetypSelect"
|
||||
v-model="selectedAbgabetyp"
|
||||
class="form-select"
|
||||
:aria-label="$p.t('abgabetool/abgabetyp_auswaehlen')"
|
||||
:disabled="!abgabeSearchEnabled"
|
||||
@change="loadTermine();"
|
||||
>
|
||||
<option :key="defaultTyp.paabgabetyp_kurzbz" selected :value="defaultTyp.paabgabetyp_kurzbz">{{defaultTyp.bezeichnung}}</option>
|
||||
<option v-for="typ in abgabetypen" :key="typ.paabgabetyp_kurzbz" :value="typ.paabgabetyp_kurzbz">{{typ.bezeichnung}}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-2">
|
||||
<h6>{{ $p.t('abgabetool/termin') }}:</h6>
|
||||
<select
|
||||
ref="termin"
|
||||
id="terminSelect"
|
||||
v-model="selectedTermin"
|
||||
class="form-select"
|
||||
:aria-label="$p.t('abgabetool/termin_auswaehlen')"
|
||||
:disabled="!abgabeSearchEnabled"
|
||||
>
|
||||
<option :key="defaultTermin.termin" selected :value="defaultTermin.termin">{{defaultTermin.termin_anzeige}}</option>
|
||||
<option v-for="termin in termine" :key="termin.termin" :value="termin.termin">{{termin.termin_anzeige}}</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-2">
|
||||
<h6>{{ $p.t('abgabetool/personsuche') }}:</h6>
|
||||
<input
|
||||
type="text"
|
||||
name="person-search"
|
||||
class="form-control"
|
||||
:placeholder="'name/uid/person ID/prestudent ID'"
|
||||
:disabled="!personSearchEnabled"
|
||||
v-on:keyup.enter="loadPaAbgaben"
|
||||
v-model="personSearchString"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-lg-2 align-content-end">
|
||||
<button class="btn btn-primary border-0" @click="loadPaAbgaben">{{ $p.t('abgabetool/anzeigen') }}</button>
|
||||
</div>
|
||||
<div class="col-12 col-lg-2 align-content-end">
|
||||
<button class="btn btn-secondary border-0" @click="actionDownloadZip">{{ $p.t('abgabetool/zipDownload') }}</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<core-filter-cmpt
|
||||
v-if="phrasenResolved"
|
||||
@uuidDefined="handleUuidDefined"
|
||||
ref="paabgabeTable"
|
||||
:tabulator-options="paabgabeTableOptions"
|
||||
:tabulator-events="paabgabeTableEventHandlers"
|
||||
tableOnly
|
||||
:sideMenu="false"
|
||||
/>
|
||||
|
||||
<loader ref="loader" :timeout="0"></loader>
|
||||
`
|
||||
};
|
||||
|
||||
export default ProjektabgabeUebersicht;
|
||||
@@ -68,8 +68,8 @@ export const Raumsuche = {
|
||||
handler: async () => {
|
||||
this.tableBuiltResolve()
|
||||
}
|
||||
}
|
||||
]};
|
||||
}]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isDarkMode(){
|
||||
|
||||
@@ -10,6 +10,10 @@ export default {
|
||||
// options: default, always, never
|
||||
}
|
||||
},
|
||||
inject: {
|
||||
mode: "mode",
|
||||
},
|
||||
emits: ['delete-event'],
|
||||
computed: {
|
||||
tooltipString() {
|
||||
const tooltipArray = [];
|
||||
@@ -56,6 +60,15 @@ export default {
|
||||
.fromISOTime(this.event.ende)
|
||||
.toISOTime({ suppressSeconds: true });
|
||||
},
|
||||
isFutureEvent() {
|
||||
const eventStart = luxon.DateTime.fromISO(`${this.event.datum}T${this.event.beginn}`);
|
||||
return eventStart > luxon.DateTime.now();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleDelete() {
|
||||
this.$emit('delete-event', this.event);
|
||||
},
|
||||
timeSlotDisplayClasses() {
|
||||
switch (this.$props.timeSlotDisplayBehavior) {
|
||||
case "always":
|
||||
@@ -69,8 +82,7 @@ export default {
|
||||
},
|
||||
template: /* html */`
|
||||
<div
|
||||
class="cis-renderer-reservierungen-calendar-event calendar-event-default h-100 w-100 p-1"
|
||||
>
|
||||
class="cis-renderer-reservierungen-calendar-event calendar-event-default h-100 w-100 p-1 position-relative">
|
||||
<div
|
||||
v-if="!event?.allDayEvent && event?.beginn && event?.ende"
|
||||
:class="timeSlotDisplayClasses"
|
||||
@@ -80,6 +92,15 @@ export default {
|
||||
<span>{{ end }}</span>
|
||||
</div>
|
||||
<div class="event-text" v-tooltip="tooltipString">
|
||||
<button
|
||||
v-if="isFutureEvent && event.type === 'reservierung' && event.deletable && mode !== 'Month'"
|
||||
class="btn btn-sm btn-outline-secondary position-absolute top-0 end-0 m-1"
|
||||
title="Löschen"
|
||||
@click.stop="handleDelete"
|
||||
>
|
||||
<i class="fa-solid fa-xmark"></i>
|
||||
</button>
|
||||
|
||||
<span class="event-topic">{{ event.topic }}</span>
|
||||
<span class="event-place">{{ event.ort_kurzbz }}</span>
|
||||
<span
|
||||
|
||||
@@ -0,0 +1,246 @@
|
||||
import FormInput from '../../../Form/Input.js';
|
||||
|
||||
export default {
|
||||
emits: ['create-event'],
|
||||
components: {
|
||||
FormInput
|
||||
},
|
||||
inject: {
|
||||
timeGrid: "timeGrid",
|
||||
},
|
||||
props: {
|
||||
event: { type: Object, required: true },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
timezone: FHC_JS_DATA_STORAGE_OBJECT.timezone,
|
||||
data: {},
|
||||
filteredGroups: [],
|
||||
filteredLektoren: [],
|
||||
selectedStart: null,
|
||||
selectedEnd: null,
|
||||
title: null,
|
||||
beschreibung: null,
|
||||
studiengang: null,
|
||||
semester: null,
|
||||
verband: null,
|
||||
gruppe: null,
|
||||
selectedGruppe: null,
|
||||
selectedLektoren: []
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.syncFromEvent(this.event);
|
||||
},
|
||||
|
||||
watch: {
|
||||
event: {
|
||||
handler(newEvent) {
|
||||
this.syncFromEvent(newEvent);
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
syncFromEvent(newEvent) {
|
||||
if (!newEvent) return;
|
||||
|
||||
const startTime = newEvent.start?.setZone?.(this.timezone)?.toFormat?.('HH:mm:ss');
|
||||
const endTime = newEvent.end?.setZone?.(this.timezone)?.toFormat?.('HH:mm:ss');
|
||||
|
||||
this.selectedStart = this.timeGrid.find(t => t.start === startTime)?.start || this.timeGrid[0]?.start;
|
||||
this.selectedEnd = this.timeGrid.find(t => t.end === endTime)?.end || this.timeGrid.at(-1)?.end;
|
||||
},
|
||||
saveEvent() {
|
||||
const [startHour, startMinute] = this.selectedStart.split(':').map(Number);
|
||||
const [endHour, endMinute] = this.selectedEnd.split(':').map(Number);
|
||||
const selectedStart = this.event.start.startOf('day').set({ hour: startHour, minute: startMinute });
|
||||
const selectedEnd = this.event.start.startOf('day').set({ hour: endHour, minute: endMinute });
|
||||
|
||||
const lektoren_uid = this.selectedLektoren.map(m => m.uid)
|
||||
|
||||
const spezialgruppe = this.selectedGruppe?.gruppe_kurzbz;
|
||||
|
||||
const event = {
|
||||
selectedStart: selectedStart,
|
||||
selectedEnd: selectedEnd,
|
||||
title: this.title,
|
||||
beschreibung: this.beschreibung,
|
||||
studiengang: this.studiengang,
|
||||
semester: this.semester,
|
||||
verband: this.verband,
|
||||
gruppe: this.gruppe,
|
||||
spezialgruppe: spezialgruppe,
|
||||
lektoren: lektoren_uid
|
||||
}
|
||||
|
||||
this.$emit('create-event', event);
|
||||
},
|
||||
async searchGroup(event) {
|
||||
this.filteredGroups = await this.event.createContext.room_create_information.searchGroup(event)
|
||||
},
|
||||
async searchLektor(event) {
|
||||
this.filteredLektoren = await this.event.createContext.room_create_information.searchLektor(event)
|
||||
},
|
||||
capitalize(text)
|
||||
{
|
||||
if (!text) return ''
|
||||
return text.charAt(0).toUpperCase() + text.slice(1)
|
||||
}
|
||||
},
|
||||
|
||||
template: `
|
||||
<div class="p-3">
|
||||
<h5 class="mb-3">Neue Reservierung</h5>
|
||||
<div class="row">
|
||||
<form-input
|
||||
:label="capitalize($p.t('ui', 'dateFrom'))"
|
||||
type="select"
|
||||
container-class="col-3"
|
||||
v-model="selectedStart"
|
||||
name="selectedStart"
|
||||
>
|
||||
<option
|
||||
v-for="slot in timeGrid"
|
||||
:value="slot.start"
|
||||
:key="slot.id"
|
||||
>
|
||||
{{ slot.start }}
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
:label="capitalize($p.t('ui', 'dateTo'))"
|
||||
type="select"
|
||||
container-class="col-3"
|
||||
v-model="selectedEnd"
|
||||
name="selectedEnd"
|
||||
>
|
||||
<option
|
||||
v-for="slot in timeGrid"
|
||||
:value="slot.end"
|
||||
:key="slot.id"
|
||||
>
|
||||
{{ slot.end }}
|
||||
</option>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="row">
|
||||
<form-input
|
||||
:label="capitalize($p.t('global', 'titel'))"
|
||||
type="text"
|
||||
container-class="col-3"
|
||||
v-model="title"
|
||||
name="title"
|
||||
/>
|
||||
|
||||
<form-input
|
||||
:label="capitalize($p.t('global', 'beschreibung'))"
|
||||
type="text"
|
||||
container-class="col-4"
|
||||
v-model="beschreibung"
|
||||
name="Beschreibung"
|
||||
/>
|
||||
<form-input
|
||||
v-if="event.createContext.show_all_fields"
|
||||
type="autocomplete"
|
||||
:minLength="2"
|
||||
:label="capitalize($p.t('lehre', 'lektor'))"
|
||||
:suggestions="filteredLektoren"
|
||||
placeholder="Mitarbeiter hinzufügen"
|
||||
field="label"
|
||||
v-model="selectedLektoren"
|
||||
container-class="col-5"
|
||||
@complete="searchLektor"
|
||||
multiple
|
||||
name="lektorautocomplete"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
|
||||
<div v-if="event.createContext.show_all_fields">
|
||||
<div class="row">
|
||||
<form-input
|
||||
:label="capitalize($p.t('lehre', 'studiengang'))"
|
||||
type="select"
|
||||
container-class="col-3"
|
||||
v-model="studiengang"
|
||||
name="studiengang"
|
||||
>
|
||||
<option
|
||||
v-for="studiengang in event.createContext.room_create_information.studiengaenge"
|
||||
:value="studiengang.studiengang_kz"
|
||||
:key="studiengang.studiengang_kz"
|
||||
>
|
||||
{{ studiengang.kuerzel }} ({{ studiengang.kurzbzlang }})
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
:label="capitalize($p.t('lehre', 'semester'))"
|
||||
type="select"
|
||||
container-class="col-2"
|
||||
v-model="semester"
|
||||
name="semester"
|
||||
>
|
||||
<option
|
||||
v-for="semester in event.createContext.room_create_information.semester"
|
||||
:value="semester"
|
||||
:key="semester"
|
||||
>
|
||||
{{ semester }}
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
:label="capitalize($p.t('lehre', 'verband'))"
|
||||
type="select"
|
||||
container-class="col-2"
|
||||
v-model="verband"
|
||||
name="semester"
|
||||
>
|
||||
<option
|
||||
v-for="verband in event.createContext.room_create_information.verband"
|
||||
:value="verband"
|
||||
:key="verband"
|
||||
>
|
||||
{{ verband }}
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
:label="capitalize($p.t('lehre', 'gruppe'))"
|
||||
type="select"
|
||||
container-class="col-2"
|
||||
v-model="gruppe"
|
||||
name="gruppe"
|
||||
>
|
||||
<option
|
||||
v-for="gruppe in event.createContext.room_create_information.gruppe"
|
||||
:value="gruppe"
|
||||
:key="gruppe"
|
||||
>
|
||||
{{ gruppe }}
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
:label="capitalize($p.t('lehre', 'special_group'))"
|
||||
type="autocomplete"
|
||||
:suggestions="filteredGroups"
|
||||
:placeholder="$p.t('lehre', 'addGroup')"
|
||||
field="label"
|
||||
:minLength="2"
|
||||
container-class="col-5"
|
||||
v-model="selectedGruppe"
|
||||
name="gruppeautocomplete"
|
||||
@complete="searchGroup"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<button class="btn btn-primary mt-3" @click="saveEvent">Speichern</button>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
export default {
|
||||
template:`<div>{{ $p.t('lehre','new_reservierung') }}</div>`
|
||||
}
|
||||
@@ -3,6 +3,7 @@ import LvUebersicht from "../Mylv/LvUebersicht.js";
|
||||
import ApiCisStudium from '../../../api/factory/cis/studium.js';
|
||||
|
||||
export default {
|
||||
name: 'Studium',
|
||||
data(){
|
||||
return {
|
||||
studienSemester :[],
|
||||
|
||||
@@ -0,0 +1,673 @@
|
||||
import {CoreFilterCmpt} from "../../filter/Filter.js";
|
||||
import FormForm from '../../Form/Form.js';
|
||||
import FormInput from '../../Form/Input.js';
|
||||
import PvAutoComplete from '../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js';
|
||||
|
||||
import ApiAuthinfo from '../../../api/factory/authinfo.js';
|
||||
import ApiTimelocks from "../../../api/factory/cis/zeitsperren.js";
|
||||
import ApiStvAbschlusspruefung from "../../../api/factory/stv/abschlusspruefung.js";
|
||||
|
||||
export default {
|
||||
name: 'ZeitsperrenComponent',
|
||||
components: {
|
||||
CoreFilterCmpt,
|
||||
FormForm,
|
||||
FormInput,
|
||||
PvAutoComplete
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
uid: null,
|
||||
statusNew: true,
|
||||
timeRecordingLockedUntil: '2015-08-31', //TODO(Manu) check if needed
|
||||
typesTimeLocks: ["Urlaub", "PflegeU", "ZA", "Krank", "DienstF", "DienstV", "CovidSB", "CovidKS"],
|
||||
typesHideStunden: ["Urlaub", "ZA", "Krank", "DienstF", "DienstV", "CovidSB", "CovidKS"],
|
||||
listTypenZeitsperren: [],
|
||||
listTypenErreichbarkeit: [],
|
||||
listStunden: [],
|
||||
tabulatorOptions: null,
|
||||
tabulatorEvents: [],
|
||||
originalData: {},
|
||||
zeitsperreData: {
|
||||
vondatum : new Date(),
|
||||
bisdatum: new Date(),
|
||||
vonISO : "00:00:00", //later
|
||||
bisISO: "23:59:59", //later
|
||||
erreichbarkeit_kurzbz: 'n',
|
||||
zeitsperretyp_kurzbz: 'Arzt',
|
||||
vonstunde: null,
|
||||
bisstunde: null
|
||||
},
|
||||
changedData: {},
|
||||
selectedVertretung: null,
|
||||
filteredMitarbeiter: [],
|
||||
abortController: {
|
||||
mitarbeiter: null
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
dienstverhinderungen() {
|
||||
return {
|
||||
"Eheschließung": "a) " + this.$p.t('zeitsperren', 'eheschliessung'),
|
||||
"Geburt eigenes Kind": "b) " + this.$p.t('zeitsperren', 'geburt'),
|
||||
"Heirat Kind/Geschwister": "c) " + this.$p.t('zeitsperren', 'heirat'),
|
||||
"Eigene Sponsion/Promotion": "d) " + this.$p.t('zeitsperren', 'sponsion'),
|
||||
"Lebensbedr. Erkrankung P/K/E": "e) " + this.$p.t('zeitsperren', 'erkrankung_lebensbedr'),
|
||||
"Ableben P/K/E": "f) " + this.$p.t('zeitsperren', 'ableben'),
|
||||
"Bestattung G/S/G": "g) " + this.$p.t('zeitsperren', 'bestattung'),
|
||||
"Wohnungswechsel": "h) " + this.$p.t('zeitsperren', 'umzug'),
|
||||
"Bundesheer": "i) " + this.$p.t('zeitsperren', 'bundesheer'),
|
||||
"Volksschultag": "j) " + this.$p.t('zeitsperren', 'volksschultag')};
|
||||
},
|
||||
showInfo(){
|
||||
return this.zeitsperreData.zeitsperretyp_kurzbz === 'DienstF';
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
actionEditZeitsperre(zeitsperre_id){
|
||||
this.statusNew = false;
|
||||
return this.$api
|
||||
.call(ApiTimelocks.loadZeitsperre(zeitsperre_id))
|
||||
.then(response => {
|
||||
this.originalData = structuredClone(response.data);
|
||||
this.zeitsperreData = structuredClone(response.data);
|
||||
|
||||
this.selectedVertretung = {
|
||||
label: this.getPersonLabel(this.zeitsperreData.ma_titelpre, this.zeitsperreData.ma_nachname, this.zeitsperreData.ma_vorname, this.zeitsperreData.ma_titelpost, this.zeitsperreData.vertretung_uid),
|
||||
person_id: this.zeitsperreData.ma_person_id,
|
||||
mitarbeiter_uid: this.zeitsperreData.vertretung_uid
|
||||
};
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
actionDeleteZeitsperre(zeitsperre_id){
|
||||
this.$fhcAlert
|
||||
.confirmDelete()
|
||||
.then(result => result
|
||||
? zeitsperre_id
|
||||
: Promise.reject({ handled: true })
|
||||
)
|
||||
.then(() => this.deleteZeitsperre(zeitsperre_id))
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
saveZeitsperre(zeitsperreId = null) {
|
||||
const isNew = !zeitsperreId;
|
||||
|
||||
let payload = isNew
|
||||
? { ...this.zeitsperreData } // add
|
||||
: this.getChangedFields(this.originalData, // edit
|
||||
this.zeitsperreData);
|
||||
|
||||
if (!isNew && Object.keys(payload).length === 0) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const request = isNew
|
||||
? ApiTimelocks.addZeitsperre(this.uid, payload)
|
||||
: ApiTimelocks.editZeitsperre(zeitsperreId, payload);
|
||||
|
||||
return this.$refs.dataZeitsperre
|
||||
.call(request)
|
||||
.then(() => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
|
||||
|
||||
this.reset();
|
||||
this.reload();
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
deleteZeitsperre(zeitsperre_id){
|
||||
return this.$api
|
||||
.call(ApiTimelocks.deleteZeitsperre(zeitsperre_id))
|
||||
.then(response => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError)
|
||||
.finally(()=> {
|
||||
this.reload();
|
||||
});
|
||||
},
|
||||
searchMitarbeiter(event) {
|
||||
if (this.abortController.mitarbeiter) {
|
||||
this.abortController.mitarbeiter.abort();
|
||||
}
|
||||
|
||||
this.abortController.mitarbeiter = new AbortController();
|
||||
|
||||
return this.$api
|
||||
.call(ApiStvAbschlusspruefung.getMitarbeiter(event.query))
|
||||
.then(result => {
|
||||
this.filteredMitarbeiter = [];
|
||||
for (let mitarbeiter of result.data.retval) {
|
||||
this.filteredMitarbeiter.push(
|
||||
{
|
||||
label: this.getPersonLabel(
|
||||
mitarbeiter.titelpre,
|
||||
mitarbeiter.nachname,
|
||||
mitarbeiter.vorname,
|
||||
mitarbeiter.titelpost,
|
||||
mitarbeiter.mitarbeiter_uid
|
||||
),
|
||||
person_id: mitarbeiter.person_id,
|
||||
mitarbeiter_uid: mitarbeiter.mitarbeiter_uid
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
getPersonLabel(titelpre, nachname, vorname, titelpost, uid) {
|
||||
if(!uid)
|
||||
return '';
|
||||
return nachname + ' ' + vorname + (titelpre ? ' ' + titelpre : '') + (titelpost ? ' ' + titelpost : '') + (uid ? ' (' + uid + ')' : '');
|
||||
},
|
||||
reload() {
|
||||
if (this.$refs.table)
|
||||
this.$refs.table.reloadTable();
|
||||
},
|
||||
reset(){
|
||||
this.statusNew = true;
|
||||
this.selectedVertretung = null;
|
||||
this.zeitsperreData = {
|
||||
vondatum : new Date(),
|
||||
bisdatum: new Date(),
|
||||
vonISO : "00:00:00", //later
|
||||
bisISO: "23:59:59", //later
|
||||
erreichbarkeit_kurzbz: 'n',
|
||||
zeitsperretyp_kurzbz: 'Arzt',
|
||||
vonstunde: null,
|
||||
bisstunde: null
|
||||
};
|
||||
this.originalData = {};
|
||||
},
|
||||
handleChangeVonStunde(){
|
||||
let stunde = this.zeitsperreData.vonstunde;
|
||||
const result = this.listStunden.find(item => item.stunde === stunde);
|
||||
if (!result) {
|
||||
this.zeitsperreData.vonISO = '00:00:00';
|
||||
return;
|
||||
}
|
||||
this.zeitsperreData.vonISO = result.beginn;
|
||||
},
|
||||
handleChangeBisStunde(){
|
||||
let stunde = this.zeitsperreData.bisstunde;
|
||||
const result = this.listStunden.find(item => item.stunde === stunde);
|
||||
if (!result) {
|
||||
this.zeitsperreData.bisISO = '23:59:59';
|
||||
return;
|
||||
}
|
||||
this.zeitsperreData.bisISO = result.ende;
|
||||
},
|
||||
handleStunden(){
|
||||
if (this.typesHideStunden.includes(this.zeitsperreData.zeitsperretyp_kurzbz)){
|
||||
this.zeitsperreData.vonstunde = null;
|
||||
this.zeitsperreData.bisstunde = null;
|
||||
this.zeitsperreData.vonISO = '00:00:00';
|
||||
this.zeitsperreData.bisISO = '23:59:59';
|
||||
}
|
||||
},
|
||||
copyDateForBis(){
|
||||
this.zeitsperreData.bisdatum = this.zeitsperreData.vondatum;
|
||||
},
|
||||
getChangedFields(original, current) {
|
||||
const diff = {};
|
||||
|
||||
Object.keys(current).forEach((key) => {
|
||||
if (current[key] !== original[key]) {
|
||||
diff[key] = current[key];
|
||||
}
|
||||
});
|
||||
return diff;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedVertretung(newVal) {
|
||||
this.zeitsperreData.vertretung_uid = newVal?.mitarbeiter_uid || null;
|
||||
},
|
||||
'zeitsperreData.zeitsperretyp_kurzbz'(newVal) {
|
||||
if (newVal === 'DienstV') {
|
||||
// set first key as default
|
||||
if (!this.zeitsperreData.bezeichnung) {
|
||||
const firstKey = Object.keys(this.dienstverhinderungen)[0];
|
||||
this.zeitsperreData.bezeichnung = firstKey;
|
||||
}
|
||||
} else {
|
||||
this.zeitsperreData.bezeichnung = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$api.call(ApiAuthinfo.getAuthUID()).then(res => {
|
||||
|
||||
//check if there is a user, passed via route
|
||||
const urlUid = this.$route?.query?.uid;
|
||||
this.uid = urlUid ? urlUid : res.data.uid;
|
||||
|
||||
this.tabulatorOptions = {
|
||||
ajaxURL: 'dummy',
|
||||
ajaxRequestFunc: () =>
|
||||
this.$api.call(ApiTimelocks.getTimelocksUser(this.uid)),
|
||||
ajaxResponse: (url, params, response) => response.data,
|
||||
columns: [
|
||||
{title:"bezeichnung", field:"bezeichnung"},
|
||||
{title:"Grund", field:"beschreibung"},
|
||||
{title:"Von", field:"vondatum",
|
||||
formatter: function (cell) {
|
||||
const dateStr = cell.getValue();
|
||||
if (!dateStr) return "";
|
||||
|
||||
const date = new Date(dateStr);
|
||||
return date.toLocaleString("de-DE", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
}
|
||||
},
|
||||
{title:"Bis", field:"bisdatum",
|
||||
formatter: function (cell) {
|
||||
const dateStr = cell.getValue();
|
||||
if (!dateStr) return "";
|
||||
|
||||
const date = new Date(dateStr);
|
||||
return date.toLocaleString("de-DE", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
});
|
||||
}
|
||||
},
|
||||
{title:"vonstunde", field:"vonstunde", visible: false},
|
||||
{title:"bisstunde", field:"bisstunde", visible: false},
|
||||
{title:"Vertretung", field:"vertretung"},
|
||||
{title:"Erreichbarkeit", field:"erreichbarkeit_beschreibung"},
|
||||
{title:"zeitsperre_id", field:"zeitsperre_id", visible: false},
|
||||
{title:"mitarbeiter_uid", field:"mitarbeiter_uid", visible: false},
|
||||
{title:"freigabeamum", field:"freigabeamum", visible: false,
|
||||
formatter: function (cell) {
|
||||
const value = cell.getValue();
|
||||
return value === null
|
||||
? ''
|
||||
: '<i class="fa fa-check text-success"></i>';
|
||||
}
|
||||
},
|
||||
{title: 'Aktionen', field: 'actions',
|
||||
minWidth: 150, // Ensures Action-buttons will be always fully displayed
|
||||
formatter: (cell, formatterParams, onRendered) => {
|
||||
let container = document.createElement('div');
|
||||
container.className = "d-flex gap-2";
|
||||
|
||||
let button = document.createElement('button');
|
||||
button.className = 'btn btn-outline-secondary btn-action';
|
||||
button.innerHTML = '<i class="fa fa-edit"></i>';
|
||||
button.title = this.$p.t('ui', 'bearbeiten');
|
||||
button.addEventListener('click', (event) =>
|
||||
this.actionEditZeitsperre(cell.getData().zeitsperre_id)
|
||||
);
|
||||
if(cell.getData().zeitsperretyp_kurzbz == 'DienstV' || cell.getData().zeitsperretyp_kurzbz == 'ZVerfueg'){
|
||||
button.disabled = true;
|
||||
}
|
||||
//TODO(Manu) check if needed
|
||||
if(this.typesTimeLocks.includes(cell.getData().zeitsperretyp_kurzbz) && (cell.getData().vondatum < this.timeRecordingLockedUntil)){
|
||||
button.disabled = true;
|
||||
}
|
||||
container.append(button);
|
||||
|
||||
button = document.createElement('button');
|
||||
button.className = 'btn btn-outline-secondary btn-action';
|
||||
button.innerHTML = '<i class="fa fa-xmark"></i>';
|
||||
button.title = this.$p.t('ui', 'loeschen');
|
||||
button.addEventListener('click', () =>
|
||||
//this.deleteZeitsperre(cell.getData().zeitsperre_id)
|
||||
this.actionDeleteZeitsperre(cell.getData().zeitsperre_id)
|
||||
);
|
||||
if(cell.getData().zeitsperretyp_kurzbz == 'Urlaub' || cell.getData().zeitsperretyp_kurzbz == 'ZVerfueg'){
|
||||
button.disabled = true;
|
||||
}
|
||||
//TODO(Manu) check if needed
|
||||
if(this.typesTimeLocks.includes(cell.getData().zeitsperretyp_kurzbz) && (cell.getData().vondatum < this.timeRecordingLockedUntil)){
|
||||
button.disabled = true;
|
||||
}
|
||||
container.append(button);
|
||||
|
||||
return container;
|
||||
},
|
||||
frozen: true
|
||||
},
|
||||
]
|
||||
};
|
||||
this.tabulatorEvents = [
|
||||
{
|
||||
event: 'tableBuilt',
|
||||
handler: async() => {
|
||||
await this.$p.loadCategory(['global', 'person', 'zeitsperren', 'ui', 'abschlusspruefung']);
|
||||
|
||||
let cm = this.$refs.table.tabulator.columnManager;
|
||||
|
||||
cm.getColumnByField('bezeichnung').component.updateDefinition({
|
||||
title: this.$p.t('person', 'grund')
|
||||
});
|
||||
cm.getColumnByField('beschreibung').component.updateDefinition({
|
||||
title: this.$p.t('global', 'bezeichnung')
|
||||
});
|
||||
cm.getColumnByField('vondatum').component.updateDefinition({
|
||||
title: this.$p.t('ui', 'von')
|
||||
});
|
||||
cm.getColumnByField('bisdatum').component.updateDefinition({
|
||||
title: this.$p.t('global', 'bis')
|
||||
});
|
||||
cm.getColumnByField('vonstunde').component.updateDefinition({
|
||||
title: this.$p.t('zeitsperren', 'stunde_von')
|
||||
});
|
||||
cm.getColumnByField('bisstunde').component.updateDefinition({
|
||||
title: this.$p.t('zeitsperren', 'stunde_bis')
|
||||
});
|
||||
cm.getColumnByField('vertretung').component.updateDefinition({
|
||||
title: this.$p.t('person', 'vertretung')
|
||||
});
|
||||
|
||||
cm.getColumnByField('erreichbarkeit_beschreibung').component.updateDefinition({
|
||||
title: this.$p.t('person', 'erreichbarkeit')
|
||||
});
|
||||
cm.getColumnByField('freigabeamum').component.updateDefinition({
|
||||
title: this.$p.t('abschlusspruefung', 'freigabe')
|
||||
});
|
||||
|
||||
/* cm.getColumnByField('actions').component.updateDefinition({
|
||||
title: this.$p.t('global', 'aktionen')
|
||||
});*/
|
||||
|
||||
}
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
this.$api
|
||||
.call(ApiTimelocks.getTypenZeitsperren())
|
||||
.then(result => {
|
||||
this.listTypenZeitsperren = result.data;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
this.$api
|
||||
.call(ApiTimelocks.getTypenErreichbarkeit())
|
||||
.then(result => {
|
||||
this.listTypenErreichbarkeit = result.data;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
this.$api
|
||||
.call(ApiTimelocks.getStunden())
|
||||
.then(result => {
|
||||
this.listStunden = result.data;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
},
|
||||
template: /* html */`
|
||||
<div class="zeitsperre">
|
||||
<h4>{{$p.t('zeitsperren', 'header_zeitsperren')}} ({{uid}}) </h4>
|
||||
|
||||
<form-form class="row g-3 mt-3" ref="dataZeitsperre">
|
||||
<div class= "w-50">
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
type="select"
|
||||
:class="showInfo ? 'is-info' : ''"
|
||||
name="zeitsperretyp_kurzbz"
|
||||
:label="$p.t('person/grund')"
|
||||
v-model="zeitsperreData.zeitsperretyp_kurzbz"
|
||||
@change="handleStunden"
|
||||
>
|
||||
<option
|
||||
v-for="typ in listTypenZeitsperren"
|
||||
:key="typ.zeitsperretyp_kurzbz"
|
||||
:value="typ.zeitsperretyp_kurzbz"
|
||||
:disabled="typ.zeitsperretyp_kurzbz == 'Urlaub'"
|
||||
>
|
||||
{{typ.beschreibung}}
|
||||
</option>
|
||||
</form-input>
|
||||
<div v-if="showInfo" class="info-feedback">
|
||||
<strong> Dienstfreistellungen</strong> nur in Absprache mit HR Service eintragen!
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="zeitsperreData.zeitsperretyp_kurzbz == 'DienstV'" class="row mb-3">
|
||||
<form-input
|
||||
type="select"
|
||||
name="beschreibung"
|
||||
:label="$p.t('ui/bezeichnung')"
|
||||
v-model="zeitsperreData.bezeichnung"
|
||||
>
|
||||
<option v-for="(beschreibung, key) in dienstverhinderungen"
|
||||
:key="key"
|
||||
:value="key">{{beschreibung}}
|
||||
</option>
|
||||
|
||||
</form-input>
|
||||
</div>
|
||||
<div v-else class="row mb-3">
|
||||
<form-input
|
||||
type="text"
|
||||
name="beschreibung"
|
||||
:label="$p.t('ui/bezeichnung')"
|
||||
v-model="zeitsperreData.bezeichnung"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="mb-3 col-2">
|
||||
<form-input
|
||||
type="DatePicker"
|
||||
name="vondatum"
|
||||
:label="$p.t('ui/from')"
|
||||
v-model="zeitsperreData.vondatum"
|
||||
auto-apply
|
||||
:enable-time-picker="false"
|
||||
format="dd.MM.yyyy"
|
||||
text-input
|
||||
preview-format="dd.MM.yyyy"
|
||||
:teleport="true"
|
||||
required
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="mb-3 col-1 d-flex align-items-end">
|
||||
<button
|
||||
class="btn btn-outline-secondary"
|
||||
title="Für Bis-Datum übernehmen"
|
||||
@click.prevent="copyDateForBis"
|
||||
>
|
||||
<i class="fa-solid fa-arrow-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 col-3">
|
||||
<form-input
|
||||
v-if="!typesHideStunden.includes(zeitsperreData.zeitsperretyp_kurzbz)"
|
||||
type="select"
|
||||
name="vonstunde"
|
||||
:label="$p.t('zeitsperren/stunde')"
|
||||
v-model="zeitsperreData.vonstunde"
|
||||
@change="handleChangeVonStunde"
|
||||
>
|
||||
<option value='null'>*</option>
|
||||
<option
|
||||
v-for="std in listStunden"
|
||||
:key="std.stunde"
|
||||
:value="std.stunde"
|
||||
>
|
||||
{{std.stunde}} ({{std.beginn}} - {{std.ende}})
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Uncomment to use timestamp VON
|
||||
<div class="mb-3 col-3">
|
||||
<form-input
|
||||
type="text"
|
||||
name="vonISO"
|
||||
label="vonISO"
|
||||
v-model="zeitsperreData.vonISO"
|
||||
auto-apply
|
||||
:enable-time-picker="true"
|
||||
format="dd.MM.yyyy HH:mm"
|
||||
text-input
|
||||
preview-format="dd.MM.yyyy HH:mm"
|
||||
:teleport="true"
|
||||
>
|
||||
{{timestampHoursVon}}
|
||||
</form-input>
|
||||
</div>
|
||||
-->
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="mb-3 col-2">
|
||||
<form-input
|
||||
type="DatePicker"
|
||||
name="bisdatum"
|
||||
:label="$p.t('global/bis')"
|
||||
v-model="zeitsperreData.bisdatum"
|
||||
auto-apply
|
||||
:enable-time-picker="false"
|
||||
format="dd.MM.yyyy"
|
||||
text-input
|
||||
preview-format="dd.MM.yyyy"
|
||||
:teleport="true"
|
||||
required
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="mb-3 col-1"></div>
|
||||
|
||||
<div class="mb-3 col-3">
|
||||
<form-input
|
||||
v-if="!typesHideStunden.includes(zeitsperreData.zeitsperretyp_kurzbz)"
|
||||
type="select"
|
||||
name="bisstunde"
|
||||
:label="$p.t('zeitsperren/stunde')"
|
||||
v-model="zeitsperreData.bisstunde"
|
||||
@change="handleChangeBisStunde"
|
||||
>
|
||||
<option value='null'>*</option>
|
||||
<option
|
||||
v-for="std in listStunden"
|
||||
:key="std.stunde"
|
||||
:value="std.stunde"
|
||||
>
|
||||
{{std.stunde}} ({{std.beginn}} - {{std.ende}})
|
||||
</option>
|
||||
</form-input>
|
||||
</div>
|
||||
|
||||
<!-- Uncomment to use timestamp BIS
|
||||
<div class="mb-3 col-3">
|
||||
<form-input
|
||||
type="text"
|
||||
name="bisISO"
|
||||
label="bisISO"
|
||||
v-model="zeitsperreData.bisISO"
|
||||
auto-apply
|
||||
:enable-time-picker="true"
|
||||
format="dd.MM.yyyy HH:mm"
|
||||
text-input
|
||||
preview-format="dd.MM.yyyy HH:mm"
|
||||
:teleport="true"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
-->
|
||||
|
||||
</div>
|
||||
|
||||
<div class= "w-50">
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
type="autocomplete"
|
||||
name="vertretung_uid"
|
||||
:label="$p.t('person/vertretung')"
|
||||
v-model="selectedVertretung"
|
||||
optionLabel="label"
|
||||
optionValue="mitarbeiter_uid"
|
||||
dropdown
|
||||
forceSelection
|
||||
:suggestions="filteredMitarbeiter"
|
||||
@complete="searchMitarbeiter"
|
||||
:min-length="3"
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row align-items-end">
|
||||
<div class="mb-3 col-4">
|
||||
<form-input
|
||||
type="select"
|
||||
name="erreichbarkeit"
|
||||
:label="$p.t('person/erreichbarkeit')"
|
||||
v-model="zeitsperreData.erreichbarkeit_kurzbz"
|
||||
>
|
||||
<option
|
||||
v-for="typ in listTypenErreichbarkeit"
|
||||
:key="typ.erreichbarkeit_kurzbz"
|
||||
:value="typ.erreichbarkeit_kurzbz"
|
||||
>
|
||||
{{typ.beschreibung}}
|
||||
</option>
|
||||
</form-input>
|
||||
</div>
|
||||
|
||||
<div class="mb-3 col-3">
|
||||
<button
|
||||
v-if="statusNew"
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="saveZeitsperre()">
|
||||
{{$p.t('zeitsperren', 'addZeitsperre')}}
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
type="button"
|
||||
class="btn btn-warning"
|
||||
@click="saveZeitsperre(zeitsperreData.zeitsperre_id)">
|
||||
{{$p.t('zeitsperren', 'saveZeitsperre')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</form-form>
|
||||
|
||||
<div class="d-flex align-items-start text-muted small">
|
||||
<i class="fa fa-circle-info me-2 mt-1"></i>
|
||||
<div>
|
||||
<strong>{{$p.t('alert', 'attention')}}</strong><br>
|
||||
{{$p.t('zeitsperren', 'info_zeitsperrenMoreDays')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
<core-filter-cmpt
|
||||
v-if="tabulatorOptions"
|
||||
ref="table"
|
||||
:tabulator-options="tabulatorOptions"
|
||||
:tabulator-events="tabulatorEvents"
|
||||
table-only
|
||||
:side-menu="false"
|
||||
reload
|
||||
:reload-btn-infotext="this.$p.t('table', 'reload')"
|
||||
>
|
||||
</core-filter-cmpt>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,72 @@
|
||||
import ApiLehre from "../../api/factory/lehre.js";
|
||||
import {capitalize} from "../../helpers/StringHelpers.js";
|
||||
|
||||
const options = Vue.ref([]);
|
||||
const params = Vue.ref({});
|
||||
let appContext = null;
|
||||
|
||||
export function setupContext(globalProps) {
|
||||
appContext = globalProps
|
||||
}
|
||||
|
||||
// bind and watch api params via reference
|
||||
export function bindParams(paramsRef) {
|
||||
Vue.watch(
|
||||
paramsRef,
|
||||
(newVal) => {
|
||||
params.value = { ...newVal };
|
||||
fetchLehreinheiten(newVal.lv_id, newVal.sem_kurzbz);
|
||||
},
|
||||
{ immediate: true, deep: true }
|
||||
);
|
||||
}
|
||||
|
||||
async function fetchLehreinheiten(lv_id, sem_kurzbz) {
|
||||
appContext.$api.call(ApiLehre.getLeForLv(lv_id, sem_kurzbz)).then(res => {
|
||||
|
||||
const data = []
|
||||
// TODO: could be done on server in some shared function, copied from anw extension for now
|
||||
res.data?.retval?.forEach(entry => {
|
||||
|
||||
const existing = data.find(e => e.lehreinheit_id === entry.lehreinheit_id)
|
||||
if (existing) {
|
||||
// supplement info
|
||||
existing.infoString += ', '
|
||||
if (entry.gruppe_kurzbz !== null && entry.direktinskription == false) {
|
||||
existing.infoString += entry.gruppe_kurzbz
|
||||
} else {
|
||||
existing.infoString += entry.kurzbzlang + '-' + entry.semester
|
||||
+ (entry.verband ? entry.verband : '')
|
||||
+ (entry.gruppe ? entry.gruppe : '')
|
||||
}
|
||||
} else {
|
||||
// entries are supposed to be fetched ordered by non null gruppe_kurzbz first
|
||||
// so a new entry will always start with those groups, others are appended afterwards
|
||||
entry.infoString = entry.kurzbz + ' - ' + entry.lehrform_kurzbz + ' - '
|
||||
if (entry.gruppe_kurzbz !== null && entry.direktinskription == false) {
|
||||
entry.infoString += entry.gruppe_kurzbz
|
||||
} else {
|
||||
entry.infoString += entry.kurzbzlang + '-' + entry.semester
|
||||
+ (entry.verband ? entry.verband : '')
|
||||
+ (entry.gruppe ? entry.gruppe : '')
|
||||
}
|
||||
|
||||
data.push(entry)
|
||||
}
|
||||
})
|
||||
|
||||
options.value = [...data]
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// export the module and relevant fields via reactive
|
||||
const LehreinheitenModule = Vue.reactive({
|
||||
options,
|
||||
optionLabel: 'infoString',
|
||||
placeholder: capitalize(Vue.computed(()=>appContext?.$p.t('lehre/lehreinheit'))),
|
||||
setupContext,
|
||||
bindParams
|
||||
});
|
||||
|
||||
export default LehreinheitenModule;
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
export const MobilityLegende = {
|
||||
name: 'MobilityLegende',
|
||||
template:`
|
||||
<div class="col-auto" style="max-width: 60vw">
|
||||
<!-- TODO: phrasen definieren & verwenden-->
|
||||
<div class="row" style="font-weight: bold"><h6>Legende</h6></div>
|
||||
<div class="row"><h6>(i) ... Incoming</h6></div>
|
||||
<div class="row"><h6>(o) ... Outgoing</h6></div>
|
||||
<div class="row"><h6>(ar) ... angerechnet </h6></div>
|
||||
<div class="row"><h6>(iar) ... intern angerechnet</h6></div>
|
||||
<div class="row"><h6>(nz) ... nicht zugelassen</h6></div>
|
||||
<div class="row"><h6>(ma) ... MitarbeiterIn</h6></div>
|
||||
<div class="row"><h6>(a.o.) ... Außerordentliche/r HörerIn</h6></div>
|
||||
<div class="row"><h6>(d.d.) ... Double Degree Program</h6></div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
|
||||
export default MobilityLegende;
|
||||
@@ -75,6 +75,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
switchFilter(evt) {
|
||||
console.log(evt);
|
||||
this.$emit('switchFilter', evt.currentTarget.value);
|
||||
},
|
||||
applyFilterConfig() {
|
||||
|
||||
@@ -7,6 +7,12 @@ export function useEventLoader(rangeInterval, getPromiseFunc) {
|
||||
const allEvents = Vue.computed(() => events.value.concat(loadingEvents.value));
|
||||
const lv = Vue.ref(null);
|
||||
const eventsLoaded = [];
|
||||
const reservierbarMap = Vue.ref({});
|
||||
|
||||
const mergeReservierbarMap = (incoming) => {
|
||||
if (!incoming) return;
|
||||
reservierbarMap.value = { ...reservierbarMap.value, ...incoming };
|
||||
};
|
||||
|
||||
const mergePromiseArr = (n, o) => {
|
||||
if (Array.isArray(n))
|
||||
@@ -128,6 +134,7 @@ export function useEventLoader(rangeInterval, getPromiseFunc) {
|
||||
lv.value = res.value.meta.lv;
|
||||
|
||||
events.value = events.value.concat(res.value.data);
|
||||
mergeReservierbarMap(res.value.data?.reservierbarMap);
|
||||
loadingEvents.value = [];
|
||||
}
|
||||
})
|
||||
@@ -135,15 +142,15 @@ export function useEventLoader(rangeInterval, getPromiseFunc) {
|
||||
};
|
||||
|
||||
Vue.watchEffect(reload);
|
||||
|
||||
|
||||
const reset = () => {
|
||||
loading_id = 0;
|
||||
events.value = [];
|
||||
loadingEvents.value = [];
|
||||
reservierbarMap.value = {};
|
||||
eventsLoaded.splice(0, eventsLoaded.length);
|
||||
|
||||
reload();
|
||||
}
|
||||
|
||||
return { events: allEvents, lv, reset }
|
||||
}
|
||||
return { events: allEvents, lv, reservierbarMap, reset }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,19 @@
|
||||
export function capitalize(string) {
|
||||
if (!string) return '';
|
||||
return string[0].toUpperCase() + string.slice(1);
|
||||
|
||||
// ref unwrap if we receive such
|
||||
if (Vue.isRef(string)) {
|
||||
return Vue.computed(() => {
|
||||
const val = Vue.unref(string);
|
||||
return (val && typeof val === 'string') ? val.charAt(0).toUpperCase() + val.slice(1) : '';
|
||||
});
|
||||
}
|
||||
|
||||
// just a plain string, return a plain string
|
||||
if (typeof string === 'string') {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
return '';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export function debounce(fn, delay) {
|
||||
let timeoutId;
|
||||
return (...args) => {
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => {
|
||||
fn(...args)
|
||||
}, delay);
|
||||
};
|
||||
}
|
||||
@@ -11,11 +11,6 @@ $("document").ready(function() {
|
||||
$("#saveProtocolBtn, #freigebenProtocolBtn").click(
|
||||
function() {
|
||||
|
||||
var freigebendata = {
|
||||
freigeben: false,
|
||||
password: null
|
||||
}
|
||||
|
||||
var data = {
|
||||
abschlussbeurteilung_kurzbz: $("#abschlussbeurteilung_kurzbz").val(),
|
||||
protokoll: $("#protokoll").val(),
|
||||
@@ -25,11 +20,16 @@ $("document").ready(function() {
|
||||
|
||||
if ($(this).prop("id") === 'freigebenProtocolBtn')
|
||||
{
|
||||
freigebendata.freigeben = true;
|
||||
freigebendata.password = $("#password").val();
|
||||
Pruefungsprotokoll.freigebendata.freigeben = true;
|
||||
Pruefungsprotokoll.freigebendata.password = $("#password").val();
|
||||
}
|
||||
else
|
||||
{
|
||||
Pruefungsprotokoll.freigebendata.freigeben = false;
|
||||
Pruefungsprotokoll.freigebendata.password = null;
|
||||
}
|
||||
|
||||
var checkFields = Pruefungsprotokoll.checkFields(data, freigebendata, $("#verfCheck").prop('checked'));
|
||||
var checkFields = Pruefungsprotokoll.checkFields(data, $("#verfCheck").prop('checked'));
|
||||
$("#protocolform td").removeClass('has-error');
|
||||
if (checkFields.length > 0)
|
||||
{
|
||||
@@ -50,7 +50,7 @@ $("document").ready(function() {
|
||||
return;
|
||||
}
|
||||
|
||||
Pruefungsprotokoll.saveProtokoll($("#abschlusspruefung_id").val(), freigebendata, data);
|
||||
Pruefungsprotokoll.saveProtokoll($("#abschlusspruefung_id").val(), data);
|
||||
}
|
||||
)
|
||||
|
||||
@@ -71,6 +71,10 @@ $("document").ready(function() {
|
||||
|
||||
var Pruefungsprotokoll = {
|
||||
abschlussbeurteilung_kurzbz: '',
|
||||
freigebendata: {
|
||||
freigeben: false,
|
||||
password: null
|
||||
},
|
||||
checkVerfassung: function()
|
||||
{
|
||||
// if student not mentally and physically fit (checkbox), no grade can be set
|
||||
@@ -85,11 +89,11 @@ var Pruefungsprotokoll = {
|
||||
$("#verfNotice").html(FHC_PhrasesLib.t("abschlusspruefung", "verfNotice"));
|
||||
}
|
||||
},
|
||||
checkFields: function(data, freigebendata, verfChecked)
|
||||
checkFields: function(data, verfChecked)
|
||||
{
|
||||
var errors = [];
|
||||
|
||||
if (data.abschlussbeurteilung_kurzbz == "" && freigebendata.freigeben === true && verfChecked)
|
||||
if (data.abschlussbeurteilung_kurzbz == "" && Pruefungsprotokoll.freigebendata.freigeben === true && verfChecked)
|
||||
errors.push({"abschlussbeurteilung_kurzbz": FHC_PhrasesLib.t("abschlusspruefung", "abschlussbeurteilungLeer")});
|
||||
|
||||
var zeitregex = /^[0-2][0-9]:[0-5][0-9]$/;
|
||||
@@ -115,15 +119,19 @@ var Pruefungsprotokoll = {
|
||||
|
||||
return errors;
|
||||
},
|
||||
setSaveButtonDisabled: function()
|
||||
{
|
||||
$("#saveProtocolBtn").prop("disabled", true).prop("title", FHC_PhrasesLib.t("abschlusspruefung", "bereitsFreigegeben"));
|
||||
},
|
||||
// ajax calls
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
saveProtokoll: function(abschlusspruefung_id, freigeben, data)
|
||||
saveProtokoll: function(abschlusspruefung_id, data)
|
||||
{
|
||||
FHC_AjaxClient.ajaxCallPost(
|
||||
CALLED_PATH + '/saveProtokoll',
|
||||
{
|
||||
abschlusspruefung_id: abschlusspruefung_id,
|
||||
freigebendata: freigeben,
|
||||
freigebendata: Pruefungsprotokoll.freigebendata,
|
||||
protocoldata: data
|
||||
},
|
||||
{
|
||||
@@ -133,7 +141,7 @@ var Pruefungsprotokoll = {
|
||||
var dataresponse = FHC_AjaxClient.getData(data);
|
||||
if (dataresponse.freigabedatum)
|
||||
{
|
||||
$("#saveProtocolBtn").prop("disabled", true);
|
||||
Pruefungsprotokoll.setSaveButtonDisabled();
|
||||
$("#freigegebenText").html(' ' + FHC_PhrasesLib.t("abschlusspruefung", "freigegebenAm") +
|
||||
' ' + dataresponse.freigabedatum)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export function centeredFormatter (cell)
|
||||
{
|
||||
const val = cell.getValue()
|
||||
return '<div style="display: flex; justify-content: center; align-items: center; height: 100%">'+val+'</div>'
|
||||
}
|
||||
@@ -150,6 +150,7 @@ $berechtigungen = array(
|
||||
array('lehre','Berechtigung fuer CIS-Seite'),
|
||||
array('lehre/abgabetool','Projektabgabetool, Studentenansicht'),
|
||||
array('lehre/abgabetool:download','Download von Projektarbeitsabgaben'),
|
||||
array('lehre/benotungstool','Cis4 Gesamtnoteneingabe'),
|
||||
array('lehre/freifach','Freifachverwaltung'),
|
||||
array('lehre/lehrfach','Lehrfachverwaltung'),
|
||||
array('lehre/lehrfach:begrenzt','Lehrfachverwaltung - nur aktiv aenderbar, nur aktive LF werden angezeigt'),
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
if (! defined('DB_NAME')) exit('No direct script access allowed');
|
||||
|
||||
if($result = $db->db_query("SELECT 1 FROM public.tbl_vorlage WHERE vorlage_kurzbz = 'Notenfreigabe'"))
|
||||
{
|
||||
if($db->db_num_rows($result) === 0)
|
||||
{
|
||||
$qry = "INSERT INTO public.tbl_vorlage (vorlage_kurzbz, bezeichnung, anmerkung, mimetype)
|
||||
VALUES ('Notenfreigabe', 'Notenfreigabe', null, 'text/html')
|
||||
ON CONFLICT (vorlage_kurzbz) DO NOTHING;";
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>system.tbl_vorlage: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo "<br>system.tbl_vorlage Notenfreigabe hinzugefuegt";
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user