mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 20:29:29 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b90dabeb2c | |||
| 2f1edfeeab | |||
| 414d8bd383 | |||
| 1a813e52ce | |||
| 16b238124a | |||
| 4def45907b | |||
| 202e6e88d2 | |||
| 3b2473039f | |||
| 59d1ca3409 | |||
| 1d26303333 |
@@ -64,9 +64,6 @@ $route['api/v1/system/[S|s]prache/(:any)'] = 'api/v1/system/sprache2/$1';
|
||||
$route['Cis/LvPlan/.*'] = 'Cis/LvPlan/index/$1';
|
||||
$route['Cis/MyLvPlan/.*'] = 'Cis/MyLvPlan/index/$1';
|
||||
$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['Abgabetool/Assistenz'] = 'Cis/Abgabetool/Assistenz';
|
||||
$route['Abgabetool/Assistenz/(:any)'] = 'Cis/Abgabetool/Assistenz/$1';
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
|
||||
if (!defined('BASEPATH'))
|
||||
exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class OtherLvPlan extends Auth_Controller
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'index' => ['basis/other_lv_plan:r']
|
||||
]);
|
||||
|
||||
// Load Config
|
||||
$this->load->config('calendar');
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
||||
$viewData = array(
|
||||
'timezone' => $this->config->item('timezone')
|
||||
);
|
||||
|
||||
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'OtherLvPlan']);
|
||||
}
|
||||
}
|
||||
@@ -55,16 +55,15 @@ class Profil extends Auth_Controller
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
||||
|
||||
$this->load->library('ProfilLib');
|
||||
$profil_data = $this->profillib->getView(getAuthUID());
|
||||
$profil_data = hasData($profil_data) ? getData($profil_data) : null;
|
||||
$viewData = array(
|
||||
'editable' => true,
|
||||
'editable'=>true,
|
||||
'profil_data' => $profil_data,
|
||||
'calendarSyncUrls' => $this->getCalendarSyncUrlData(),
|
||||
);
|
||||
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'profilIndex']);
|
||||
$this->load->view('CisRouterView/CisRouterView.php',['viewData' => $viewData, 'route' => 'profilIndex']);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,23 +76,20 @@ class Profil extends Auth_Controller
|
||||
$this->load->library('ProfilLib');
|
||||
$profil_data = $this->profillib->getView($uid);
|
||||
$profil_data = hasData($profil_data) ? getData($profil_data) : null;
|
||||
$viewData = array(
|
||||
$viewData = array (
|
||||
'uid' => $uid,
|
||||
'profil_data' => $profil_data,
|
||||
'permissions' => [
|
||||
'basis/other_lv_plan' => $this->permissionlib->isBerechtigt(('basis/other_lv_plan')),
|
||||
]
|
||||
'profil_data'=>$profil_data,
|
||||
);
|
||||
if ($uid == getAuthUID()) {
|
||||
if($uid == getAuthUID()){
|
||||
$viewData['editable'] = true;
|
||||
}
|
||||
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'profilViewUid']);
|
||||
$this->load->view('CisRouterView/CisRouterView.php',['viewData' => $viewData, 'route' => 'profilViewUid']);
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether a specific userID is a student or not (foreword declaration of the function isStudent in Student_model.php)
|
||||
* checks whether a specific userID is a mitarbeiter or not (foreword declaration of the function isMitarbeiter in Mitarbeiter_model.php)
|
||||
* @access public
|
||||
* @param $uid the userID used to check if it is a student
|
||||
* @param $uid the userID used to check if it is a mitarbeiter
|
||||
* @return boolean
|
||||
*/
|
||||
public function isStudent($uid)
|
||||
@@ -123,7 +119,7 @@ class Profil extends Auth_Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the adressen that are marked as zustell from the currently logged in user
|
||||
* gets the adressen that are marked as zustell from the currenlty logged in user
|
||||
* @access public
|
||||
* @return array a list of adresse_id's
|
||||
*/
|
||||
@@ -266,23 +262,23 @@ class Profil extends Auth_Controller
|
||||
$this->GemeindeModel->addDistinct();
|
||||
$this->GemeindeModel->addSelect(["name"]);
|
||||
if ($nation == "A") {
|
||||
if (isset($zip) && $zip > 999 && $zip < 32000) {
|
||||
if (isset($zip) && $zip > 999 && $zip < 32000) {
|
||||
|
||||
$gemeinde_res = $this->GemeindeModel->loadWhere(['plz' => $zip]);
|
||||
if (isError($gemeinde_res)) {
|
||||
show_error("error while trying to query bis.tbl_gemeinde");
|
||||
$gemeinde_res = $this->GemeindeModel->loadWhere(['plz' => $zip]);
|
||||
if (isError($gemeinde_res)) {
|
||||
show_error("error while trying to query bis.tbl_gemeinde");
|
||||
}
|
||||
$gemeinde_res = hasData($gemeinde_res) ? getData($gemeinde_res) : null;
|
||||
$gemeinde_res = array_map(function ($obj) {
|
||||
return $obj->name;
|
||||
}, $gemeinde_res);
|
||||
echo json_encode($gemeinde_res);
|
||||
|
||||
} else {
|
||||
echo json_encode(error("ortschaftskennziffer code was not valid"));
|
||||
}
|
||||
$gemeinde_res = hasData($gemeinde_res) ? getData($gemeinde_res) : null;
|
||||
$gemeinde_res = array_map(function ($obj) {
|
||||
return $obj->name;
|
||||
}, $gemeinde_res);
|
||||
echo json_encode($gemeinde_res);
|
||||
|
||||
} else {
|
||||
echo json_encode(error("ortschaftskennziffer code was not valid"));
|
||||
}
|
||||
} else {
|
||||
echo json_encode(error("Nation was not 'A' (Austria)"));
|
||||
echo json_encode(error("Nation was not 'A' (Austria)"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -755,29 +751,5 @@ class Profil extends Auth_Controller
|
||||
return $zutrittskarte_ausgegebenam;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the identifier, phrase, and url for each calendar sync option
|
||||
* @access private
|
||||
* @return array array of arrays, where each child array is a sync option
|
||||
*/
|
||||
private function getCalendarSyncUrlData()
|
||||
{
|
||||
return [
|
||||
[
|
||||
"identifier" => "cal_dav",
|
||||
"labelPhrase" => "profil/calendar_sync_cal_dav",
|
||||
"url" => APP_ROOT . "webdav/lvplan.php/calendars/" . $this->uid . "/LVPlan-" . $this->uid,
|
||||
],
|
||||
[
|
||||
"identifier" => "cal_dav_principal",
|
||||
"labelPhrase" => "profil/calendar_sync_cal_dav_principal",
|
||||
"url" => APP_ROOT . "webdav/lvplan.php/principals/" . $this->uid,
|
||||
],
|
||||
[
|
||||
"identifier" => "i_cal",
|
||||
"labelPhrase" => "profil/calendar_sync_i_cal",
|
||||
"url" => APP_ROOT . "webdav/google.php?cal=" . encryptData($this->uid, LVPLAN_CYPHER_KEY) . "&" . microtime(true),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class StgOrgLvPlan extends Auth_Controller
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'index' => ['basis/cis:r']
|
||||
]);
|
||||
|
||||
// Load Config
|
||||
$this->load->config('calendar');
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
||||
$viewData = array(
|
||||
'uid'=>getAuthUID(),
|
||||
'timezone' => $this->config->item('timezone')
|
||||
);
|
||||
|
||||
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'StgOrgLvPlan']);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
if (!defined('BASEPATH'))
|
||||
exit('No direct script access allowed');
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -14,9 +13,9 @@ class Cis4 extends Auth_Controller
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
array(
|
||||
'index' => 'basis/cis:r'
|
||||
)
|
||||
array(
|
||||
'index' => 'basis/cis:r'
|
||||
)
|
||||
);
|
||||
|
||||
// Load Config
|
||||
@@ -33,12 +32,12 @@ class Cis4 extends Auth_Controller
|
||||
{
|
||||
$this->load->model('person/Person_model', 'PersonModel');
|
||||
$personData = getData($this->PersonModel->getByUid(getAuthUID()))[0];
|
||||
|
||||
|
||||
$viewData = array(
|
||||
'uid' => getAuthUID(),
|
||||
'name' => $personData->vorname,
|
||||
'person_id' => $personData->person_id,
|
||||
'timezone' => $this->config->item('timezone'),
|
||||
'timezone' => $this->config->item('timezone')
|
||||
);
|
||||
|
||||
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'FhcDashboard']);
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (!defined('BASEPATH'))
|
||||
exit('No direct script access allowed');
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
use CI3_Events as Events;
|
||||
use \DateTime as DateTime;
|
||||
@@ -34,25 +33,19 @@ class LvPlan extends FHCAPI_Controller
|
||||
|
||||
parent::__construct([
|
||||
'getRoomplan' => self::PERM_LOGGED,
|
||||
'Stunden' => self::PERM_LOGGED,
|
||||
'getReservierungen' => self::PERM_LOGGED,
|
||||
'Stunden' => self::PERM_LOGGED,
|
||||
'getReservierungen' => self::PERM_LOGGED,
|
||||
'LvPlanEvents' => self::PERM_LOGGED,
|
||||
'eventsPersonal' => self::PERM_LOGGED,
|
||||
'eventsLv' => self::PERM_LOGGED,
|
||||
'getLehreinheitStudiensemester' => self::PERM_LOGGED,
|
||||
'studiensemesterDateInterval' => self::PERM_LOGGED,
|
||||
'getLvPlanForStudiensemester' => self::PERM_LOGGED,
|
||||
'getLv' => self::PERM_LOGGED,
|
||||
'eventsStgOrg' => self::PERM_LOGGED,
|
||||
'fetchFerienEvents' => self::PERM_LOGGED,
|
||||
'getStudiengaenge' => self::PERM_LOGGED,
|
||||
'getLehrverband' => self::PERM_LOGGED,
|
||||
'permissionOtherLvPlan' => self::PERM_LOGGED,
|
||||
'compactibleEventTypes' => self::PERM_LOGGED,
|
||||
'getLv' => self::PERM_LOGGED
|
||||
]);
|
||||
|
||||
$this->load->library('LogLib');
|
||||
$this->loglib->setConfigs(array(
|
||||
$this->load->library('LogLib');
|
||||
$this->loglib->setConfigs(array(
|
||||
'classIndex' => 5,
|
||||
'functionIndex' => 5,
|
||||
'lineIndex' => 4,
|
||||
@@ -60,17 +53,17 @@ class LvPlan extends FHCAPI_Controller
|
||||
'dbExecuteUser' => 'RESTful API'
|
||||
));
|
||||
|
||||
$this->load->library('form_validation');
|
||||
$this->load->library('form_validation');
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* fetches LvPlan and Moodle events together
|
||||
* @access public
|
||||
*
|
||||
*/
|
||||
* fetches LvPlan and Moodle events together
|
||||
* @access public
|
||||
*
|
||||
*/
|
||||
public function LvPlanEvents()
|
||||
{
|
||||
$hasLv = $this->input->post('lv_id');
|
||||
@@ -90,30 +83,24 @@ class LvPlan extends FHCAPI_Controller
|
||||
// form validation
|
||||
$this->form_validation->set_rules('start_date', "start_date", "required");
|
||||
$this->form_validation->set_rules('end_date', "end_date", "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);
|
||||
$uid = $this->input->post('uid', true);
|
||||
|
||||
// disallow accessing other user's lv plan if missing permission
|
||||
if ($uid && $uid !== getAuthUID() && !$this->permissionlib->isBerechtigt('basis/other_lv_plan')) {
|
||||
$this->terminateWithError("Missing permission to view other users' timetables!");
|
||||
}
|
||||
|
||||
// fetching lvplan events
|
||||
$result = $this->stundenplanlib->getEventsUser($start_date, $end_date, $uid);
|
||||
$result = $this->stundenplanlib->getEventsUser($start_date, $end_date);
|
||||
$lvplanEvents = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
// fetching moodle events
|
||||
$moodleEvents = $uid ? [] : $this->fetchMoodleEvents($start_date, $end_date);
|
||||
$moodleEvents = $this->fetchMoodleEvents($start_date, $end_date);
|
||||
|
||||
// fetching ferien events
|
||||
$ferienEvents = $this->fetchFerienEvents($start_date, $end_date, $uid);
|
||||
|
||||
$ferienEvents = $this->fetchFerienEvents($start_date, $end_date);
|
||||
|
||||
|
||||
$this->terminateWithSuccess(array_merge(
|
||||
$lvplanEvents,
|
||||
@@ -122,45 +109,6 @@ class LvPlan extends FHCAPI_Controller
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches LvPlan for studiengang / semester / verband / gruppe
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function eventsStgOrg()
|
||||
{
|
||||
$this->load->library('StundenplanLib');
|
||||
|
||||
// form validation
|
||||
$this->form_validation->set_rules('start_date', "start_date", "required");
|
||||
$this->form_validation->set_rules('end_date', "end_date", "required");
|
||||
//$this->form_validation->set_rules('stg_kz', "stg_kz", "required"); //no validation show empty calendar
|
||||
|
||||
if (!$this->form_validation->run()) {
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
$stgOrgEvents = [];
|
||||
$ferienEvents = [];
|
||||
} else {
|
||||
$start_date = $this->input->post('start_date', true);
|
||||
$end_date = $this->input->post('end_date', true);
|
||||
$stg_kz = $this->input->post('stg_kz', true);
|
||||
$sem = $this->input->post('sem', true);
|
||||
$verband = $this->input->post('verband', true);
|
||||
$gruppe = $this->input->post('gruppe', true);
|
||||
|
||||
$result = $this->stundenplanlib->getEventsStgOrg($start_date, $end_date, $stg_kz, $sem, $verband, $gruppe);
|
||||
$stgOrgEvents = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$result = $this->stundenplanlib->fetchFerienTageEvents($start_date, $end_date, $stg_kz);
|
||||
$ferienEvents = $this->getDataOrTerminateWithError($result);
|
||||
}
|
||||
|
||||
$this->terminateWithSuccess(array_merge(
|
||||
$stgOrgEvents,
|
||||
$ferienEvents
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches LvPlan and Ferien events together for the lv
|
||||
*
|
||||
@@ -174,7 +122,7 @@ class LvPlan extends FHCAPI_Controller
|
||||
$this->form_validation->set_rules('start_date', "start_date", "required");
|
||||
$this->form_validation->set_rules('end_date', "end_date", "required");
|
||||
$this->form_validation->set_rules('lv_id', "lv_id", "required|integer");
|
||||
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
@@ -189,6 +137,7 @@ class LvPlan extends FHCAPI_Controller
|
||||
|
||||
// fetching ferien events
|
||||
$ferienEvents = $this->fetchFerienEvents($start_date, $end_date);
|
||||
|
||||
|
||||
$this->terminateWithSuccess(array_merge(
|
||||
$lvplanEvents,
|
||||
@@ -197,42 +146,40 @@ class LvPlan extends FHCAPI_Controller
|
||||
}
|
||||
|
||||
//TODO: delete this function if we don't use the old calendar export endpoints anymore
|
||||
public function studiensemesterDateInterval($date)
|
||||
{
|
||||
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
|
||||
$studiensemester = $this->StudiensemesterModel->getByDate(date_format(date_create($date), 'Y-m-d'));
|
||||
$studiensemester = current($this->getDataOrTerminateWithError($studiensemester));
|
||||
public function studiensemesterDateInterval($date){
|
||||
$this->load->model('organisation/Studiensemester_model','StudiensemesterModel');
|
||||
$studiensemester =$this->StudiensemesterModel->getByDate(date_format(date_create($date),'Y-m-d'));
|
||||
$studiensemester =current($this->getDataOrTerminateWithError($studiensemester));
|
||||
$this->terminateWithSuccess($studiensemester);
|
||||
}
|
||||
|
||||
public function getLvPlanForStudiensemester($studiensemester, $lvid)
|
||||
{
|
||||
public function getLvPlanForStudiensemester($studiensemester,$lvid){
|
||||
$this->load->library('StundenplanLib');
|
||||
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
|
||||
|
||||
$studiensemester_result = $this->StudiensemesterModel->loadWhere(["studiensemester_kurzbz" => $studiensemester]);
|
||||
$this->load->model('organisation/Studiensemester_model','StudiensemesterModel');
|
||||
|
||||
$studiensemester_result = $this->StudiensemesterModel->loadWhere(["studiensemester_kurzbz"=>$studiensemester]);
|
||||
$studiensemester_result = current($this->getDataOrTerminateWithError($studiensemester_result));
|
||||
$timespan_start = new DateTime($studiensemester_result->start);
|
||||
$timespan_ende = new DateTime($studiensemester_result->ende);
|
||||
$lvplan = $this->stundenplanlib->getStundenplan(date_format($timespan_start, 'Y-m-d'), date_format($timespan_ende, 'Y-m-d'), $lvid);
|
||||
$lvplan = $this->stundenplanlib->getStundenplan(date_format($timespan_start, 'Y-m-d'),date_format($timespan_ende, 'Y-m-d'), $lvid);
|
||||
$this->terminateWithSuccess($lvplan);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* fetches Stunden layout from database
|
||||
* @access public
|
||||
*
|
||||
*/
|
||||
public function Stunden()
|
||||
/**
|
||||
* fetches Stunden layout from database
|
||||
* @access public
|
||||
*
|
||||
*/
|
||||
public function Stunden()
|
||||
{
|
||||
$this->load->model('ressource/Stunde_model', 'StundeModel');
|
||||
|
||||
$this->StundeModel->addOrder('stunde', 'ASC');
|
||||
$stunden = $this->StundeModel->load();
|
||||
|
||||
$stunden = $this->getDataOrTerminateWithError($stunden);
|
||||
$stunden = $this->getDataOrTerminateWithError($stunden);
|
||||
|
||||
$this->terminateWithSuccess($stunden);
|
||||
}
|
||||
@@ -263,10 +210,10 @@ class LvPlan extends FHCAPI_Controller
|
||||
$roomplan_data = $this->stundenplanlib->getRoomplan($ort_kurzbz, $start_date, $end_date);
|
||||
|
||||
$roomplan_data = $this->getDataOrTerminateWithError($roomplan_data);
|
||||
|
||||
|
||||
$this->terminateWithSuccess($roomplan_data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gets the reservierungen of a room if the ort_kurzbz parameter is
|
||||
* supplied otherwise gets the reservierungen of the lvplan of a student
|
||||
@@ -279,27 +226,25 @@ class LvPlan extends FHCAPI_Controller
|
||||
{
|
||||
$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);
|
||||
$uid = $this->input->post('uid', true);
|
||||
|
||||
// get data
|
||||
$this->load->library('StundenplanLib');
|
||||
|
||||
$result = $this->stundenplanlib->getReservierungen($start_date, $end_date, $ort_kurzbz, $uid);
|
||||
$result = $this->stundenplanlib->getReservierungen($start_date, $end_date, $ort_kurzbz);
|
||||
|
||||
$result = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
|
||||
public function getLehreinheitStudiensemester($lehreinheit_id)
|
||||
{
|
||||
public function getLehreinheitStudiensemester($lehreinheit_id){
|
||||
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
|
||||
$this->LehreinheitModel->addSelect(["studiensemester_kurzbz"]);
|
||||
$result = $this->LehreinheitModel->load($lehreinheit_id);
|
||||
@@ -342,68 +287,6 @@ class LvPlan extends FHCAPI_Controller
|
||||
return $this->terminateWithSuccess(current($result));
|
||||
}
|
||||
|
||||
public function getStudiengaenge()
|
||||
{
|
||||
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
|
||||
|
||||
$this->StudiengangModel->addOrder('typ');
|
||||
$this->StudiengangModel->addOrder('kurzbz');
|
||||
$result = $this->StudiengangModel->loadWhere([
|
||||
'aktiv' => true
|
||||
]);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
return $this->terminateWithSuccess($data);
|
||||
}
|
||||
|
||||
public function getLehrverband($studiengang_kz, $semester = null, $verband = null)
|
||||
{
|
||||
$this->load->model('organisation/Lehrverband_model', 'LehrverbandModel');
|
||||
|
||||
$where = [
|
||||
'aktiv' => true,
|
||||
'studiengang_kz' => $studiengang_kz,
|
||||
];
|
||||
|
||||
if ($semester !== null && $semester !== 'null' && $semester !== 'undefined') {
|
||||
$where['semester'] = $semester;
|
||||
}
|
||||
if ($verband !== null && $verband !== 'null' && $verband !== 'undefined') {
|
||||
$where['verband'] = $verband;
|
||||
}
|
||||
|
||||
$this->LehrverbandModel->addOrder('studiengang_kz');
|
||||
$this->LehrverbandModel->addOrder('semester');
|
||||
$this->LehrverbandModel->addOrder('verband');
|
||||
$this->LehrverbandModel->addOrder('gruppe');
|
||||
$result = $this->LehrverbandModel->loadWhere($where);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
return $this->terminateWithSuccess($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current user has permission to view other users' timetables
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function permissionOtherLvPlan()
|
||||
{
|
||||
$this->terminateWithSuccess($this->permissionlib->isBerechtigt('basis/other_lv_plan'));
|
||||
}
|
||||
|
||||
/**
|
||||
* get event types which can be compacted in lv plan display
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function compactibleEventTypes()
|
||||
{
|
||||
$this->terminateWithSuccess(["lehreinheit", "reservierung"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* fetch moodle events
|
||||
*
|
||||
@@ -416,19 +299,19 @@ class LvPlan extends FHCAPI_Controller
|
||||
$this->load->config('calendar');
|
||||
|
||||
$tz = new DateTimeZone($this->config->item('timezone'));
|
||||
|
||||
|
||||
$start = new DateTime($start_date);
|
||||
$start->setTimezone($tz);
|
||||
|
||||
|
||||
$end = new DateTime($end_date);
|
||||
$end->setTimezone($tz);
|
||||
$end->modify('+1 day -1 second');
|
||||
|
||||
|
||||
$moodle_events = [];
|
||||
|
||||
|
||||
Events::trigger(
|
||||
'moodleCalendarEvents',
|
||||
function &() use (&$moodle_events) {
|
||||
function & () use (&$moodle_events) {
|
||||
return $moodle_events;
|
||||
},
|
||||
[
|
||||
@@ -448,23 +331,23 @@ class LvPlan extends FHCAPI_Controller
|
||||
* @param string $end_date
|
||||
* @return array
|
||||
*/
|
||||
private function fetchFerienEvents($start_date, $end_date, $uid = null)
|
||||
private function fetchFerienEvents($start_date, $end_date)
|
||||
{
|
||||
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
|
||||
$this->load->model('education/Studentlehrverband_model', 'StudentLehrverbandModel');
|
||||
|
||||
$currentStudiensemester = $this->StudiensemesterModel->getByDate($start_date);
|
||||
$currentStudiensemester = $this->getDataOrTerminateWithError($currentStudiensemester);
|
||||
|
||||
|
||||
if ($currentStudiensemester) {
|
||||
$studentsemester_kurzbz = current($currentStudiensemester)->studiensemester_kurzbz;
|
||||
|
||||
$studiengang = $this->StudentLehrverbandModel->loadWhere([
|
||||
"student_uid" => $uid ?? getAuthUID(),
|
||||
"student_uid" => getAuthUID(),
|
||||
"studiensemester_kurzbz" => $studentsemester_kurzbz
|
||||
]);
|
||||
$studiengang = $this->getDataOrTerminateWithError($studiengang);
|
||||
|
||||
|
||||
if ($studiengang)
|
||||
$studiengang_kz = current($studiengang)->studiengang_kz;
|
||||
else
|
||||
@@ -474,7 +357,7 @@ class LvPlan extends FHCAPI_Controller
|
||||
}
|
||||
|
||||
$ferienEvents = $this->stundenplanlib->fetchFerienTageEvents($start_date, $end_date, $studiengang_kz);
|
||||
|
||||
|
||||
return $this->getDataOrTerminateWithError($ferienEvents);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
<?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 OtherLvPlan extends FHCAPI_Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Object initialization
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getBasicUserAttributesForLvPlanDisplay' => self::PERM_LOGGED,
|
||||
]);
|
||||
|
||||
$this->load->library('PermissionLib');
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->load->model('ressource/mitarbeiter_model', 'MitarbeiterModel');
|
||||
$this->load->model('person/Benutzer_model', 'BenutzerModel');
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* retrieves basic user attributes necessary for LV Plan display
|
||||
* @access public
|
||||
* @param $uid the userID for which basic attributes are retrieved
|
||||
* @return stdClass consisting of basic user attributes
|
||||
*/
|
||||
public function getBasicUserAttributesForLvPlanDisplay($uid)
|
||||
{
|
||||
$isMitarbeiterResult = $this->MitarbeiterModel->isMitarbeiter($uid);
|
||||
$isMitarbeiter = getData($isMitarbeiterResult);
|
||||
$isStudent = !$isMitarbeiter;
|
||||
|
||||
$this->BenutzerModel->addSelect(["foto", "vorname", "nachname"]);
|
||||
$this->BenutzerModel->addJoin("tbl_person", "person_id");
|
||||
$personResult = $this->BenutzerModel->load([$uid]);
|
||||
$person = hasData($personResult) ? getData($personResult) : null;
|
||||
|
||||
$result = [
|
||||
"username" => $uid,
|
||||
"is_student" => $isStudent,
|
||||
"is_mitarbeiter" => $isMitarbeiter,
|
||||
"foto" => $person[0]->foto,
|
||||
"vorname" => $person[0]->vorname,
|
||||
"nachname" => $person[0]->nachname,
|
||||
];
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Private methods
|
||||
|
||||
}
|
||||
|
||||
@@ -1,517 +0,0 @@
|
||||
<?php
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Base Site URL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| URL to your CodeIgniter root. Typically this will be your base URL,
|
||||
| WITH a trailing slash:
|
||||
|
|
||||
| http://example.com/
|
||||
|
|
||||
| If this is not set then CodeIgniter will try guess the protocol, domain
|
||||
| and path to your installation. However, you should always configure this
|
||||
| explicitly and never rely on auto-guessing, especially in production
|
||||
| environments.
|
||||
|
|
||||
*/
|
||||
$config['base_url'] = 'https://c3p0.dev.technikum-wien.at/ma1434/core/FHC-Core/';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Index File
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Typically this will be your index.php file, unless you've renamed it to
|
||||
| something else. If you are using mod_rewrite to remove the page set this
|
||||
| variable so that it is blank.
|
||||
|
|
||||
*/
|
||||
$config['index_page'] = 'index.ci.php';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| URI PROTOCOL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This item determines which server global should be used to retrieve the
|
||||
| URI string. The default setting of 'REQUEST_URI' works for most servers.
|
||||
| If your links do not seem to work, try one of the other delicious flavors:
|
||||
|
|
||||
| 'REQUEST_URI' Uses $_SERVER['REQUEST_URI']
|
||||
| 'QUERY_STRING' Uses $_SERVER['QUERY_STRING']
|
||||
| 'PATH_INFO' Uses $_SERVER['PATH_INFO']
|
||||
|
|
||||
| WARNING: If you set this to 'PATH_INFO', URIs will always be URL-decoded!
|
||||
*/
|
||||
$config['uri_protocol'] = 'REQUEST_URI';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| URL suffix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option allows you to add a suffix to all URLs generated by CodeIgniter.
|
||||
| For more information please see the user guide:
|
||||
|
|
||||
| http://codeigniter.com/user_guide/general/urls.html
|
||||
*/
|
||||
$config['url_suffix'] = '';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Language
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This determines which set of language files should be used. Make sure
|
||||
| there is an available translation if you intend to use something other
|
||||
| than english.
|
||||
|
|
||||
*/
|
||||
$config['language'] = '';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Character Set
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This determines which character set is used by default in various methods
|
||||
| that require a character set to be provided.
|
||||
|
|
||||
| See http://php.net/htmlspecialchars for a list of supported charsets.
|
||||
|
|
||||
*/
|
||||
$config['charset'] = 'UTF-8';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Enable/Disable System Hooks
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you would like to use the 'hooks' feature you must enable it by
|
||||
| setting this variable to TRUE (boolean). See the user guide for details.
|
||||
|
|
||||
*/
|
||||
$config['enable_hooks'] = FALSE;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Class Extension Prefix
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This item allows you to set the filename/classname prefix when extending
|
||||
| native libraries. For more information please see the user guide:
|
||||
|
|
||||
| http://codeigniter.com/user_guide/general/core_classes.html
|
||||
| http://codeigniter.com/user_guide/general/creating_libraries.html
|
||||
|
|
||||
*/
|
||||
$config['subclass_prefix'] = 'FHC_';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Composer auto-loading
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Enabling this setting will tell CodeIgniter to look for a Composer
|
||||
| package auto-loader script in application/vendor/autoload.php.
|
||||
|
|
||||
| $config['composer_autoload'] = TRUE;
|
||||
|
|
||||
| Or if you have your vendor/ directory located somewhere else, you
|
||||
| can opt to set a specific path as well:
|
||||
|
|
||||
| $config['composer_autoload'] = '/path/to/vendor/autoload.php';
|
||||
|
|
||||
| For more information about Composer, please visit http://getcomposer.org/
|
||||
|
|
||||
| Note: This will NOT disable or override the CodeIgniter-specific
|
||||
| autoloading (application/config/autoload.php)
|
||||
*/
|
||||
$config['composer_autoload'] = FALSE;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Allowed URL Characters
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This lets you specify which characters are permitted within your URLs.
|
||||
| When someone tries to submit a URL with disallowed characters they will
|
||||
| get a warning message.
|
||||
|
|
||||
| As a security measure you are STRONGLY encouraged to restrict URLs to
|
||||
| as few characters as possible. By default only these are allowed: a-z 0-9~%.:_-
|
||||
|
|
||||
| Leave blank to allow all characters -- but only if you are insane.
|
||||
|
|
||||
| The configured value is actually a regular expression character group
|
||||
| and it will be executed as: ! preg_match('/^[<permitted_uri_chars>]+$/i
|
||||
|
|
||||
| DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!!
|
||||
|
|
||||
*/
|
||||
$config['permitted_uri_chars'] = 'a-z 0-9~%.:_\-';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Enable Query Strings
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default CodeIgniter uses search-engine friendly segment based URLs:
|
||||
| example.com/who/what/where/
|
||||
|
|
||||
| By default CodeIgniter enables access to the $_GET array. If for some
|
||||
| reason you would like to disable it, set 'allow_get_array' to FALSE.
|
||||
|
|
||||
| You can optionally enable standard query string based URLs:
|
||||
| example.com?who=me&what=something&where=here
|
||||
|
|
||||
| Options are: TRUE or FALSE (boolean)
|
||||
|
|
||||
| The other items let you set the query string 'words' that will
|
||||
| invoke your controllers and its functions:
|
||||
| example.com/index.php?c=controller&m=function
|
||||
|
|
||||
| Please note that some of the helpers won't work as expected when
|
||||
| this feature is enabled, since CodeIgniter is designed primarily to
|
||||
| use segment based URLs.
|
||||
|
|
||||
*/
|
||||
$config['allow_get_array'] = TRUE;
|
||||
$config['enable_query_strings'] = FALSE;
|
||||
$config['controller_trigger'] = 'c';
|
||||
$config['function_trigger'] = 'm';
|
||||
$config['directory_trigger'] = 'd';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Error Logging Threshold
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| You can enable error logging by setting a threshold over zero. The
|
||||
| threshold determines what gets logged. Threshold options are:
|
||||
|
|
||||
| 0 = Disables logging, Error logging TURNED OFF
|
||||
| 1 = Error Messages (including PHP errors)
|
||||
| 2 = Debug Messages
|
||||
| 3 = Informational Messages
|
||||
| 4 = All Messages
|
||||
|
|
||||
| You can also pass an array with threshold levels to show individual error types
|
||||
|
|
||||
| array(2) = Debug Messages, without Error Messages
|
||||
|
|
||||
| For a live site you'll usually only enable Errors (1) to be logged otherwise
|
||||
| your log files will fill up very fast.
|
||||
|
|
||||
*/
|
||||
$config['log_threshold'] = 1;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Error Logging Directory Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Leave this BLANK unless you would like to set something other than the default
|
||||
| application/logs/ directory. Use a full server path with trailing slash.
|
||||
|
|
||||
*/
|
||||
$config['log_path'] = '';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Log File Extension
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The default filename extension for log files. The default 'php' allows for
|
||||
| protecting the log files via basic scripting, when they are to be stored
|
||||
| under a publicly accessible directory.
|
||||
|
|
||||
| Note: Leaving it blank will default to 'php'.
|
||||
|
|
||||
*/
|
||||
$config['log_file_extension'] = 'log';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Log File Permissions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The file system permissions to be applied on newly created log files.
|
||||
|
|
||||
| IMPORTANT: This MUST be an integer (no quotes) and you MUST use octal
|
||||
| integer notation (i.e. 0700, 0644, etc.)
|
||||
*/
|
||||
$config['log_file_permissions'] = 0644;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Date Format for Logs
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Each item that is logged has an associated date. You can use PHP date
|
||||
| codes to set your own date formatting
|
||||
|
|
||||
*/
|
||||
$config['log_date_format'] = 'Y-m-d H:i:s';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Error Views Directory Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Leave this BLANK unless you would like to set something other than the default
|
||||
| application/views/errors/ directory. Use a full server path with trailing slash.
|
||||
|
|
||||
*/
|
||||
$config['error_views_path'] = '';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Directory Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Leave this BLANK unless you would like to set something other than the default
|
||||
| application/cache/ directory. Use a full server path with trailing slash.
|
||||
|
|
||||
*/
|
||||
$config['cache_path'] = '';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Include Query String
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Whether to take the URL query string into consideration when generating
|
||||
| output cache files. Valid options are:
|
||||
|
|
||||
| FALSE = Disabled
|
||||
| TRUE = Enabled, take all query parameters into account.
|
||||
| Please be aware that this may result in numerous cache
|
||||
| files generated for the same page over and over again.
|
||||
| array('q') = Enabled, but only take into account the specified list
|
||||
| of query parameters.
|
||||
|
|
||||
*/
|
||||
$config['cache_query_string'] = FALSE;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Encryption Key
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If you use the Encryption class, you must set an encryption key.
|
||||
| See the user guide for more info.
|
||||
|
|
||||
| http://codeigniter.com/user_guide/libraries/encryption.html
|
||||
|
|
||||
*/
|
||||
$config['encryption_key'] = '';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Session Variables
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| 'sess_driver'
|
||||
|
|
||||
| The storage driver to use: files, database, redis, memcached
|
||||
|
|
||||
| 'sess_cookie_name'
|
||||
|
|
||||
| The session cookie name, must contain only [0-9a-z_-] characters
|
||||
|
|
||||
| 'sess_expiration'
|
||||
|
|
||||
| The number of SECONDS you want the session to last.
|
||||
| Setting to 0 (zero) means expire when the browser is closed.
|
||||
|
|
||||
| 'sess_save_path'
|
||||
|
|
||||
| The location to save sessions to, driver dependent.
|
||||
|
|
||||
| For the 'files' driver, it's a path to a writable directory.
|
||||
| WARNING: Only absolute paths are supported!
|
||||
|
|
||||
| For the 'database' driver, it's a table name.
|
||||
| Please read up the manual for the format with other session drivers.
|
||||
|
|
||||
| IMPORTANT: You are REQUIRED to set a valid save path!
|
||||
|
|
||||
| 'sess_match_ip'
|
||||
|
|
||||
| Whether to match the user's IP address when reading the session data.
|
||||
|
|
||||
| 'sess_time_to_update'
|
||||
|
|
||||
| How many seconds between CI regenerating the session ID.
|
||||
| NOTE: Keep it as it is to prevent security issues (https://en.wikipedia.org/wiki/Session_fixation)
|
||||
|
|
||||
| 'sess_regenerate_destroy'
|
||||
|
|
||||
| Whether to destroy session data associated with the old session ID
|
||||
| when auto-regenerating the session ID. When set to FALSE, the data
|
||||
| will be later deleted by the garbage collector.
|
||||
|
|
||||
| Other session cookie settings are shared with the rest of the application,
|
||||
| except for 'cookie_prefix' and 'cookie_httponly', which are ignored here.
|
||||
|
|
||||
*/
|
||||
$config['sess_driver'] = 'files';
|
||||
$config['sess_cookie_name'] = 'sess_ci_session';
|
||||
$config['sess_expiration'] = 1800; // Session expires every 30 minutes
|
||||
$config['sess_save_path'] = NULL;
|
||||
$config['sess_match_ip'] = FALSE;
|
||||
$config['sess_time_to_update'] = 300;
|
||||
$config['sess_regenerate_destroy'] = FALSE;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cookie Related Variables
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| 'cookie_prefix' = Set a cookie name prefix if you need to avoid collisions
|
||||
| 'cookie_domain' = Set to .your-domain.com for site-wide cookies
|
||||
| 'cookie_path' = Typically will be a forward slash
|
||||
| 'cookie_secure' = Cookie will only be set if a secure HTTPS connection exists.
|
||||
| 'cookie_httponly' = Cookie will only be accessible via HTTP(S) (no javascript)
|
||||
|
|
||||
| Note: These settings (with the exception of 'cookie_prefix' and
|
||||
| 'cookie_httponly') will also affect sessions.
|
||||
|
|
||||
*/
|
||||
$config['cookie_prefix'] = '';
|
||||
$config['cookie_domain'] = '';
|
||||
$config['cookie_path'] = '/';
|
||||
$config['cookie_secure'] = FALSE;
|
||||
$config['cookie_httponly'] = FALSE;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Standardize newlines
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Determines whether to standardize newline characters in input data,
|
||||
| meaning to replace \r\n, \r, \n occurrences with the PHP_EOL value.
|
||||
|
|
||||
| This is particularly useful for portability between UNIX-based OSes,
|
||||
| (usually \n) and Windows (\r\n).
|
||||
|
|
||||
*/
|
||||
$config['standardize_newlines'] = FALSE;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Global XSS Filtering
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Determines whether the XSS filter is always active when GET, POST or
|
||||
| COOKIE data is encountered
|
||||
|
|
||||
| WARNING: This feature is DEPRECATED and currently available only
|
||||
| for backwards compatibility purposes!
|
||||
|
|
||||
*/
|
||||
$config['global_xss_filtering'] = FALSE;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cross Site Request Forgery
|
||||
|--------------------------------------------------------------------------
|
||||
| Enables a CSRF cookie token to be set. When set to TRUE, token will be
|
||||
| checked on a submitted form. If you are accepting user data, it is strongly
|
||||
| recommended CSRF protection be enabled.
|
||||
|
|
||||
| 'csrf_token_name' = The token name
|
||||
| 'csrf_cookie_name' = The cookie name
|
||||
| 'csrf_expire' = The number in seconds the token should expire.
|
||||
| 'csrf_regenerate' = Regenerate token on every submission
|
||||
| 'csrf_exclude_uris' = Array of URIs which ignore CSRF checks
|
||||
*/
|
||||
$config['csrf_protection'] = FALSE;
|
||||
$config['csrf_token_name'] = 'csrf_test_name';
|
||||
$config['csrf_cookie_name'] = 'csrf_cookie_name';
|
||||
$config['csrf_expire'] = 7200;
|
||||
$config['csrf_regenerate'] = TRUE;
|
||||
$config['csrf_exclude_uris'] = array();
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Output Compression
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Enables Gzip output compression for faster page loads. When enabled,
|
||||
| the output class will test whether your server supports Gzip.
|
||||
| Even if it does, however, not all browsers support compression
|
||||
| so enable only if you are reasonably sure your visitors can handle it.
|
||||
|
|
||||
| Only used if zlib.output_compression is turned off in your php.ini.
|
||||
| Please do not use it together with httpd-level output compression.
|
||||
|
|
||||
| VERY IMPORTANT: If you are getting a blank page when compression is enabled it
|
||||
| means you are prematurely outputting something to your browser. It could
|
||||
| even be a line of whitespace at the end of one of your scripts. For
|
||||
| compression to work, nothing can be sent before the output buffer is called
|
||||
| by the output class. Do not 'echo' any values with compression enabled.
|
||||
|
|
||||
*/
|
||||
$config['compress_output'] = FALSE;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Master Time Reference
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Options are 'local' or any PHP supported timezone. This preference tells
|
||||
| the system whether to use your server's local time as the master 'now'
|
||||
| reference, or convert it to the configured one timezone. See the 'date
|
||||
| helper' page of the user guide for information regarding date handling.
|
||||
|
|
||||
*/
|
||||
$config['time_reference'] = 'local';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Rewrite PHP Short Tags
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If your PHP installation does not have short tag support enabled CI
|
||||
| can rewrite the tags on-the-fly, enabling you to utilize that syntax
|
||||
| in your view files. Options are TRUE or FALSE (boolean)
|
||||
|
|
||||
| Note: You need to have eval() enabled for this to work.
|
||||
|
|
||||
*/
|
||||
$config['rewrite_short_tags'] = FALSE;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Reverse Proxy IPs
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| If your server is behind a reverse proxy, you must whitelist the proxy
|
||||
| IP addresses from which CodeIgniter should trust headers such as
|
||||
| HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP in order to properly identify
|
||||
| the visitor's IP address.
|
||||
|
|
||||
| You can use both an array or a comma-separated list of proxy addresses,
|
||||
| as well as specifying whole subnets. Here are a few examples:
|
||||
|
|
||||
| Comma-separated: '10.0.1.200,192.168.5.0/24'
|
||||
| Array: array('10.0.1.200', '192.168.5.0/24')
|
||||
*/
|
||||
$config['proxy_ips'] = '';
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| FHComplete Build Version
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Version Number of the Current Build
|
||||
| This is used to invalidate Cache for JS and CSS Files
|
||||
|
|
||||
| Example: 2019102901
|
||||
*/
|
||||
$config['fhcomplete_build_version'] = '2019102903';
|
||||
@@ -1,122 +0,0 @@
|
||||
<?php
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
defined('DB_HOST') OR require_once './config/system.config.inc.php'; // For CLI-Migrations
|
||||
|
||||
/*
|
||||
| -------------------------------------------------------------------
|
||||
| DATABASE CONNECTIVITY SETTINGS
|
||||
| -------------------------------------------------------------------
|
||||
| This file will contain the settings needed to access your database.
|
||||
|
|
||||
| For complete instructions please consult the 'Database Connection'
|
||||
| page of the User Guide.
|
||||
|
|
||||
| -------------------------------------------------------------------
|
||||
| EXPLANATION OF VARIABLES
|
||||
| -------------------------------------------------------------------
|
||||
|
|
||||
| ['dsn'] The full DSN string describe a connection to the database.
|
||||
| ['hostname'] The hostname of your database server.
|
||||
| ['username'] The username used to connect to the database
|
||||
| ['password'] The password used to connect to the database
|
||||
| ['database'] The name of the database you want to connect to
|
||||
| ['dbdriver'] The database driver. e.g.: mysqli.
|
||||
| Currently supported:
|
||||
| cubrid, ibase, mssql, mysql, mysqli, oci8,
|
||||
| odbc, pdo, postgre, sqlite, sqlite3, sqlsrv
|
||||
| ['dbprefix'] You can add an optional prefix, which will be added
|
||||
| to the table name when using the Query Builder class
|
||||
| ['pconnect'] TRUE/FALSE - Whether to use a persistent connection
|
||||
| ['db_debug'] TRUE/FALSE - Whether database errors should be displayed.
|
||||
| ['cache_on'] TRUE/FALSE - Enables/disables query caching
|
||||
| ['cachedir'] The path to the folder where cache files should be stored
|
||||
| ['char_set'] The character set used in communicating with the database
|
||||
| ['dbcollat'] The character collation used in communicating with the database
|
||||
| NOTE: For MySQL and MySQLi databases, this setting is only used
|
||||
| as a backup if your server is running PHP < 5.2.3 or MySQL < 5.0.7
|
||||
| (and in table creation queries made with DB Forge).
|
||||
| There is an incompatibility in PHP with mysql_real_escape_string() which
|
||||
| can make your site vulnerable to SQL injection if you are using a
|
||||
| multi-byte character set and are running versions lower than these.
|
||||
| Sites using Latin-1 or UTF-8 database character set and collation are unaffected.
|
||||
| ['swap_pre'] A default table prefix that should be swapped with the dbprefix
|
||||
| ['encrypt'] Whether or not to use an encrypted connection.
|
||||
|
|
||||
| 'mysql' (deprecated), 'sqlsrv' and 'pdo/sqlsrv' drivers accept TRUE/FALSE
|
||||
| 'mysqli' and 'pdo/mysql' drivers accept an array with the following options:
|
||||
|
|
||||
| 'ssl_key' - Path to the private key file
|
||||
| 'ssl_cert' - Path to the public key certificate file
|
||||
| 'ssl_ca' - Path to the certificate authority file
|
||||
| 'ssl_capath' - Path to a directory containing trusted CA certificats in PEM format
|
||||
| 'ssl_cipher' - List of *allowed* ciphers to be used for the encryption, separated by colons (':')
|
||||
| 'ssl_verify' - TRUE/FALSE; Whether verify the server certificate or not ('mysqli' only)
|
||||
|
|
||||
| ['compress'] Whether or not to use client compression (MySQL only)
|
||||
| ['stricton'] TRUE/FALSE - forces 'Strict Mode' connections
|
||||
| - good for ensuring strict SQL while developing
|
||||
| ['ssl_options'] Used to set various SSL options that can be used when making SSL connections.
|
||||
| ['failover'] array - A array with 0 or more data for connections if the main should fail.
|
||||
| ['save_queries'] TRUE/FALSE - Whether to "save" all executed queries.
|
||||
| NOTE: Disabling this will also effectively disable both
|
||||
| $this->db->last_query() and profiling of DB queries.
|
||||
| When you run a query, with this setting set to TRUE (default),
|
||||
| CodeIgniter will store the SQL statement for debugging purposes.
|
||||
| However, this may cause high memory usage, especially if you run
|
||||
| a lot of SQL queries ... disable this to avoid that problem.
|
||||
|
|
||||
| The $active_group variable lets you choose which connection group to
|
||||
| make active. By default there is only one group (the 'default' group).
|
||||
|
|
||||
| The $query_builder variables lets you determine whether or not to load
|
||||
| the query builder class.
|
||||
*/
|
||||
$active_group = 'default';
|
||||
$query_builder = TRUE;
|
||||
|
||||
$db['default'] = array(
|
||||
'dsn' => '',
|
||||
'hostname' => DB_HOST,
|
||||
'username' => DB_USER,
|
||||
'password' => DB_PASSWORD,
|
||||
'port' => DB_PORT,
|
||||
'database' => DB_NAME,
|
||||
'dbdriver' => 'postgre',
|
||||
'dbprefix' => '',
|
||||
'pconnect' => DB_CONNECT_PERSISTENT,
|
||||
'db_debug' => (ENVIRONMENT !== 'production'),
|
||||
'cache_on' => FALSE,
|
||||
'cachedir' => '',
|
||||
'char_set' => 'utf8',
|
||||
'dbcollat' => 'utf8_general_ci',
|
||||
'swap_pre' => '',
|
||||
'encrypt' => FALSE,
|
||||
'compress' => FALSE,
|
||||
'stricton' => FALSE,
|
||||
'failover' => array(),
|
||||
'save_queries' => TRUE
|
||||
);
|
||||
|
||||
$db['system'] = array(
|
||||
'dsn' => '',
|
||||
'hostname' => DB_HOST,
|
||||
'username' => 'fhcomplete',
|
||||
'password' => 'Fhcomplet3Onc4p1',
|
||||
'database' => DB_NAME,
|
||||
'port' => DB_PORT,
|
||||
'dbschema' => 'public',
|
||||
'dbdriver' => 'postgre',
|
||||
'dbprefix' => '',
|
||||
'pconnect' => DB_CONNECT_PERSISTENT,
|
||||
'db_debug' => (ENVIRONMENT !== 'production'),
|
||||
'cache_on' => FALSE,
|
||||
'cachedir' => '',
|
||||
'char_set' => 'utf8',
|
||||
'dbcollat' => 'utf8_general_ci',
|
||||
'swap_pre' => '',
|
||||
'encrypt' => FALSE,
|
||||
'compress' => FALSE,
|
||||
'stricton' => FALSE,
|
||||
'failover' => array(),
|
||||
'save_queries' => TRUE
|
||||
);
|
||||
@@ -128,7 +128,7 @@ class AntragLib
|
||||
return $this->_ci->StudierendenantragstatusModel->resumeAntraegeForAbmeldungStgl($antrag_id);
|
||||
}
|
||||
// NOTE(chris): get last status that is not pause
|
||||
$this->_ci->StudierendenantragstatusModel->addOrder('insertamum', 'DESC');
|
||||
$this->_ci->StudierendenantragstatusModel->addOrder('insertamum');
|
||||
$this->_ci->StudierendenantragstatusModel->addLimit(1);
|
||||
$result = $this->_ci->StudierendenantragstatusModel->loadWhere([
|
||||
'studierendenantrag_id' => $antrag_id,
|
||||
|
||||
@@ -40,16 +40,13 @@ class StundenplanLib
|
||||
* @return stdClass
|
||||
* @access public
|
||||
*/
|
||||
public function getEventsUser($start, $end, $uid = null)
|
||||
public function getEventsUser($start, $end)
|
||||
{
|
||||
$this->_ci =& get_instance();
|
||||
|
||||
$this->_ci->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
|
||||
|
||||
if (!$uid) {
|
||||
$uid = getAuthUID();
|
||||
}
|
||||
|
||||
$uid = getAuthUID();
|
||||
if (is_null($uid))
|
||||
return error("No UID");
|
||||
|
||||
@@ -220,7 +217,7 @@ class StundenplanLib
|
||||
* @param string $ort_kurzbz
|
||||
* @return stdClass
|
||||
*/
|
||||
public function getReservierungen($start_date, $end_date, $ort_kurzbz = '', $uid = null)
|
||||
public function getReservierungen($start_date, $end_date, $ort_kurzbz = '')
|
||||
{
|
||||
$this->_ci =& get_instance();
|
||||
|
||||
@@ -231,14 +228,14 @@ class StundenplanLib
|
||||
$this->_ci->load->model('ressource/Reservierung_model', 'ReservierungModel');
|
||||
$this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel');
|
||||
|
||||
$is_mitarbeiter = getData($this->_ci->MitarbeiterModel->isMitarbeiter($uid ?? getAuthUID()));
|
||||
$is_mitarbeiter = getData($this->_ci->MitarbeiterModel->isMitarbeiter(getAuthUID()));
|
||||
|
||||
if ($is_mitarbeiter && empty($ort_kurzbz)) {
|
||||
// request for personal lvplan show only reservations of logged in user
|
||||
$reservierungen = $this->_ci->ReservierungModel->getReservierungenMitarbeiter($start_date, $end_date, $uid);
|
||||
$reservierungen = $this->_ci->ReservierungModel->getReservierungenMitarbeiter($start_date, $end_date);
|
||||
} else {
|
||||
// querying the reservierungen
|
||||
$reservierungen = $this->_ci->ReservierungModel->getReservierungen($start_date, $end_date, $ort_kurzbz, $uid);
|
||||
$reservierungen = $this->_ci->ReservierungModel->getReservierungen($start_date, $end_date, $ort_kurzbz);
|
||||
}
|
||||
|
||||
if (isError($reservierungen))
|
||||
@@ -448,24 +445,6 @@ class StundenplanLib
|
||||
return success($ferienEventsFlattened);
|
||||
}
|
||||
|
||||
public function getEventsStgOrg( $start, $end, $stg_kz, $sem, $verband, $gruppe)
|
||||
{
|
||||
$this->_ci =& get_instance();
|
||||
|
||||
$this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel');
|
||||
|
||||
$stundenplan_data = $this->_ci->StundenplanModel->getStundenplanStudiengang($start, $end, $stg_kz, $sem, $verband, $gruppe);
|
||||
if (isError($stundenplan_data))
|
||||
return $stundenplan_data;
|
||||
$stundenplan_data = getData($stundenplan_data) ?? [];
|
||||
|
||||
$function_error = $this->expandObjectInformation($stundenplan_data);
|
||||
if ($function_error)
|
||||
return $function_error;
|
||||
|
||||
return success($stundenplan_data);
|
||||
}
|
||||
|
||||
// start of the private functions ########################################################################################################
|
||||
|
||||
// function used to sort an array of studiensemester strings
|
||||
|
||||
@@ -594,10 +594,7 @@ class Studiengang_model extends DB_Model
|
||||
$this->addSelect('p.prestudent_id');
|
||||
$this->addSelect('pers.vorname');
|
||||
$this->addSelect('pers.nachname');
|
||||
$this->addSelect("CONCAT(UPPER(pers.nachname), ' ', pers.vorname, ' (', "
|
||||
. $this->dbTable . ".bezeichnung, ', ', "
|
||||
. "UPPER(" . $this->dbTable . ".typ), "
|
||||
. "UPPER(" . $this->dbTable . ".kurzbz),')') AS name");
|
||||
$this->addSelect("CONCAT(UPPER(pers.nachname), ' ', pers.vorname, ' (', " . $this->dbTable . ".bezeichnung, ')') AS name");
|
||||
|
||||
$this->addJoin('public.tbl_prestudent p', 'studiengang_kz');
|
||||
$this->addJoin(
|
||||
|
||||
@@ -18,10 +18,10 @@ class Reservierung_model extends DB_Model
|
||||
*
|
||||
* @return stdClass
|
||||
*/
|
||||
public function getReservierungen($start_date, $end_date, $ort_kurzbz = null, $uid = null)
|
||||
public function getReservierungen($start_date, $end_date, $ort_kurzbz = null)
|
||||
{
|
||||
|
||||
$lvplan_reservierungen_query = "SELECT r.* , stund.beginn, stund.ende,
|
||||
|
||||
$lvplan_reservierungen_query="SELECT r.* , stund.beginn, stund.ende,
|
||||
CASE
|
||||
WHEN r.gruppe_kurzbz IS NOT NULL THEN r.gruppe_kurzbz
|
||||
ELSE CONCAT(UPPER(studg.typ),UPPER(studg.kurzbz),'-',COALESCE(CAST(r.semester AS varchar),'/'),COALESCE(CAST(r.verband AS varchar),'/'))
|
||||
@@ -35,7 +35,7 @@ class Reservierung_model extends DB_Model
|
||||
LEFT JOIN public.tbl_studiensemester ss2 ON slv.studiensemester_kurzbz = ss2.studiensemester_kurzbz AND ss2.start <=r.datum AND ss2.ende >= r.datum
|
||||
WHERE datum >= ? AND datum <= ? AND (ss1.studiensemester_kurzbz IS NOT NULL
|
||||
OR ss2.studiensemester_kurzbz IS NOT NULL)";
|
||||
|
||||
|
||||
$raum_reservierungen_query = "SELECT res.*, beginn, ende,
|
||||
CASE
|
||||
WHEN res.gruppe_kurzbz IS NOT NULL THEN res.gruppe_kurzbz
|
||||
@@ -46,9 +46,9 @@ class Reservierung_model extends DB_Model
|
||||
JOIN lehre.tbl_stunde ON lehre.tbl_stunde.stunde = res.stunde
|
||||
WHERE res.ort_kurzbz = ? AND datum >= ? AND datum <= ?";
|
||||
|
||||
$subquery = is_null($ort_kurzbz) ? $lvplan_reservierungen_query : $raum_reservierungen_query;
|
||||
|
||||
$query_result = $this->execReadOnlyQuery("
|
||||
$subquery = is_null($ort_kurzbz)? $lvplan_reservierungen_query:$raum_reservierungen_query;
|
||||
|
||||
$query_result= $this->execReadOnlyQuery("
|
||||
SELECT
|
||||
'reservierung' as type, beginn, ende, datum,
|
||||
COALESCE(titel, beschreibung) as topic,
|
||||
@@ -59,15 +59,15 @@ class Reservierung_model extends DB_Model
|
||||
|
||||
FROM
|
||||
(
|
||||
" . $subquery . "
|
||||
". $subquery ."
|
||||
) AS subquery
|
||||
|
||||
GROUP BY datum, beginn, ende, ort_kurzbz, titel, beschreibung
|
||||
|
||||
ORDER BY datum, beginn
|
||||
", is_null($ort_kurzbz) ? [$uid ?? getAuthUID(), $uid ?? getAuthUID(), $start_date, $end_date] : [$ort_kurzbz, $start_date, $end_date]);
|
||||
|
||||
", is_null($ort_kurzbz) ?[getAuthUID(), getAuthUID(),$start_date,$end_date]: [$ort_kurzbz, $start_date, $end_date]);
|
||||
|
||||
|
||||
return $query_result;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ class Reservierung_model extends DB_Model
|
||||
*
|
||||
* @return stdClass
|
||||
*/
|
||||
public function getReservierungenMitarbeiter($start_date, $end_date, $uid = null)
|
||||
public function getReservierungenMitarbeiter($start_date, $end_date)
|
||||
{
|
||||
|
||||
$raum_reservierungen_query = "SELECT res.*, beginn, ende,
|
||||
@@ -91,8 +91,8 @@ class Reservierung_model extends DB_Model
|
||||
|
||||
$subquery = $raum_reservierungen_query;
|
||||
|
||||
|
||||
$query_result = $this->execReadOnlyQuery("
|
||||
|
||||
$query_result= $this->execReadOnlyQuery("
|
||||
SELECT
|
||||
'reservierung' as type, beginn, ende, datum,
|
||||
COALESCE(titel, beschreibung) as topic,
|
||||
@@ -103,13 +103,13 @@ class Reservierung_model extends DB_Model
|
||||
|
||||
FROM
|
||||
(
|
||||
" . $subquery . "
|
||||
". $subquery ."
|
||||
) AS subquery
|
||||
|
||||
GROUP BY datum, beginn, ende, ort_kurzbz, titel, beschreibung
|
||||
|
||||
ORDER BY datum, beginn
|
||||
", [$uid ?? getAuthUID(), $start_date, $end_date]);
|
||||
", [getAuthUID(), $start_date, $end_date]);
|
||||
|
||||
|
||||
return $query_result;
|
||||
@@ -129,9 +129,9 @@ class Reservierung_model extends DB_Model
|
||||
$this->addJoin('public.tbl_studiensemester ss2', 'slv.studiensemester_kurzbz=ss2.studiensemester_kurzbz AND ss2.start<=r.datum AND ss2.ende>=r.datum', 'LEFT');
|
||||
$this->db->or_where('ss1.studiensemester_kurzbz IS NOT NULL', null, false);
|
||||
$this->db->or_where('ss2.studiensemester_kurzbz IS NOT NULL', null, false);
|
||||
|
||||
|
||||
$query = $this->db->get_compiled_select('campus.vw_reservierung r');
|
||||
|
||||
|
||||
return $this->execQuery($query, [$uid, $uid]);
|
||||
}
|
||||
|
||||
|
||||
@@ -388,84 +388,6 @@ class Stundenplan_model extends DB_Model
|
||||
|
||||
ORDER BY datum, beginn", [$start_date, $end_date, $ma_uid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* queries Stundenplan and filters by studiengang, semester, verband gruppe
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getStundenplanStudiengang($start_date, $end_date, $stg_kz, $sem, $verband, $gruppe) {
|
||||
|
||||
$qry_params = [$start_date, $end_date, $stg_kz];
|
||||
|
||||
$qry = "
|
||||
SELECT
|
||||
'lehreinheit' as type, beginn, ende, datum,
|
||||
CONCAT(lehrfach,'-',lehrform) as topic,
|
||||
array_agg(DISTINCT lektor) as lektor,
|
||||
array_agg(DISTINCT (gruppe,verband,semester,studiengang_kz,gruppen_kuerzel)) as gruppe,
|
||||
string_agg(DISTINCT ort_kurzbz, '/') as ort_kurzbz,
|
||||
array_agg(DISTINCT lehreinheit_id) as lehreinheit_id,
|
||||
titel, lehrfach, lehrform, lehrfach_bez, organisationseinheit, farbe, lehrveranstaltung_id
|
||||
FROM
|
||||
(
|
||||
SELECT unr,datum,beginn, ende,
|
||||
CASE
|
||||
WHEN sp.mitarbeiter_kurzbz IS NOT NULL THEN sp.mitarbeiter_kurzbz
|
||||
ELSE sp.lektor
|
||||
END as lektor,
|
||||
CASE
|
||||
WHEN gruppe_kurzbz IS NOT NULL THEN gruppe_kurzbz
|
||||
ELSE CONCAT(UPPER(sp.stg_typ),UPPER(sp.stg_kurzbz),'-',COALESCE(CAST(sp.semester AS varchar),'/'),COALESCE(CAST(sp.verband AS varchar),'/'))
|
||||
END as gruppen_kuerzel,
|
||||
(SELECT bezeichnung
|
||||
FROM public.tbl_organisationseinheit
|
||||
WHERE oe_kurzbz IN(
|
||||
SELECT oe_kurzbz
|
||||
FROM lehre.tbl_lehrveranstaltung
|
||||
WHERE lehrveranstaltung_id = sp.lehrveranstaltung_id
|
||||
)) as organisationseinheit,
|
||||
sp.ort_kurzbz, sp.studiengang_kz, sp.titel,sp.lehreinheit_id,sp.lehrfach_id,sp.anmerkung,fix,lehrveranstaltung_id,stg_kurzbzlang,stg_bezeichnung,stg_typ,fachbereich_kurzbz,lehrfach,lehrfach_bez,farbe,lehrform,anmerkung_lehreinheit,gruppe, verband, semester,stg_kurzbz
|
||||
FROM (
|
||||
SELECT sp.*
|
||||
FROM lehre.vw_stundenplan sp
|
||||
WHERE
|
||||
sp.datum >= ?
|
||||
AND sp.datum <= ?
|
||||
) sp
|
||||
JOIN lehre.tbl_stunde ON lehre.tbl_stunde.stunde = sp.stunde
|
||||
WHERE studiengang_kz = ? ";
|
||||
|
||||
if($sem != NULL)
|
||||
{
|
||||
$qry_params[] = $sem;
|
||||
$qry .= " AND (semester = ? OR semester IS NULL)";
|
||||
}
|
||||
if($verband != NULL)
|
||||
{
|
||||
$qry_params[] = $verband;
|
||||
$qry .= " AND (verband = ? OR verband IS NULL OR verband = '0' OR verband = '')";
|
||||
}
|
||||
if($gruppe != NULL)
|
||||
{
|
||||
$qry_params[] = $gruppe;
|
||||
$qry .= " AND (gruppe = ? OR gruppe IS NULL OR gruppe = '0' OR gruppe = '') ";
|
||||
}
|
||||
$qry.= " AND (
|
||||
gruppe_kurzbz is null OR EXISTS(
|
||||
SELECT 1
|
||||
FROM
|
||||
public.tbl_gruppe WHERE gruppe_kurzbz = sp.gruppe_kurzbz AND direktinskription = false
|
||||
)
|
||||
)";
|
||||
|
||||
$qry.= " ) as subquery
|
||||
|
||||
GROUP BY unr, datum, beginn, ende, titel, lehrform, lehrfach, lehrfach_bez, organisationseinheit, farbe, lehrveranstaltung_id
|
||||
ORDER BY datum, beginn; ";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, $qry_params);
|
||||
}
|
||||
|
||||
/**
|
||||
* NO STANDALONE FUNCTION - Generates a SQL query string to fetch 'stundenplan' events for a specific student within the current semester.
|
||||
|
||||
@@ -46,13 +46,12 @@ echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<link rel="stylesheet" href="../../../skin/tablesort.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="../../../skin/style.css.php" type="text/css">
|
||||
<link rel="stylesheet" type="text/css" href="../../../skin/jquery-ui-1.9.2.custom.min.css">
|
||||
<script type="text/javascript" src="../../../vendor/jquery/jquery1/jquery-1.12.4.min.js"></script>
|
||||
<script type="text/javascript" src="../../../vendor/christianbach/tablesorter/jquery.tablesorter.min.js"></script>
|
||||
<script type="text/javascript" src="../../../vendor/components/jqueryui/jquery-ui.min.js"></script>
|
||||
<script type="text/javascript" src="../../../include/js/jquery.ui.datepicker.translation.js"></script>
|
||||
<script type="text/javascript" src="../../../vendor/jquery/sizzle/sizzle.js"></script>';
|
||||
|
||||
include('../../../include/meta/jquery.php');
|
||||
include('../../../include/meta/jquery-tablesorter.php');
|
||||
|
||||
const MOODLE_ADDON_KURZBZ = 'moodle';
|
||||
|
||||
// Load Addons to get Moodle_Path
|
||||
@@ -72,7 +71,7 @@ echo '
|
||||
$("#myTable").tablesorter(
|
||||
{
|
||||
sortList: [[0,0],[1,0]],
|
||||
widgets: [\'zebra\',\'filter\']
|
||||
widgets: [\'zebra\']
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -152,9 +151,8 @@ foreach($service->result as $row)
|
||||
$person = new person();
|
||||
$person->getPersonFromBenutzer($row->operativ_uid);
|
||||
$operativ = $person->nachname.' '.$person->vorname;
|
||||
$oeBez = new organisationseinheit($row->oe_kurzbz);
|
||||
echo '<tr>';
|
||||
echo '<td>',$oeBez->bezeichnung,'</td>';
|
||||
echo '<td>',$row->oe_kurzbz,'</td>';
|
||||
echo '<td><b>'.$row->bezeichnung.'</b></td>';
|
||||
echo '<td>',$row->beschreibung,'</td>';
|
||||
echo '<td><nobr><a href="../profile/index.php?uid='.$row->design_uid.'">',$design,'</a></nobr></td>';
|
||||
|
||||
Generated
-6
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "FHC-Core",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
||||
@@ -30,11 +30,11 @@ export default {
|
||||
params: { start_date, end_date, lv_id }
|
||||
};
|
||||
},
|
||||
eventsPersonal(start_date, end_date, uid = null) {
|
||||
eventsPersonal(start_date, end_date) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/lvPlan/eventsPersonal',
|
||||
params: { start_date, end_date, uid }
|
||||
params: { start_date, end_date }
|
||||
};
|
||||
},
|
||||
eventsLv(lv_id, start_date, end_date) {
|
||||
@@ -57,11 +57,11 @@ export default {
|
||||
params: { start_date, end_date }
|
||||
};
|
||||
},
|
||||
getLvPlanReservierungen(start_date, end_date, uid = null) {
|
||||
getLvPlanReservierungen(start_date, end_date) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/LvPlan/getReservierungen',
|
||||
params: { start_date, end_date, uid }
|
||||
params: { start_date, end_date }
|
||||
};
|
||||
},
|
||||
getLehreinheitStudiensemester(lehreinheit_id) {
|
||||
@@ -92,42 +92,5 @@ export default {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/LvPlan/getLv/' + lehrveranstaltung_id
|
||||
};
|
||||
},
|
||||
eventsStgOrg(start_date, end_date, stg_kz, sem, verband, gruppe) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/lvPlan/eventsStgOrg',
|
||||
params: { start_date, end_date, stg_kz, sem, verband, gruppe }
|
||||
};
|
||||
},
|
||||
getStudiengaenge(){
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/lvPlan/getStudiengaenge'
|
||||
}
|
||||
},
|
||||
getLehrverband(stg_kz, sem){
|
||||
return {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/lvPlan/getLehrverband/${stg_kz}/${sem}`
|
||||
}
|
||||
},
|
||||
getGruppe(stg_kz, sem, verband){
|
||||
return {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/lvPlan/getLehrverband/${stg_kz}/${sem}/${verband}`
|
||||
}
|
||||
},
|
||||
checkPermissionOtherLvPlan(){
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/lvPlan/permissionOtherLvPlan',
|
||||
}
|
||||
},
|
||||
getCompactibleEventTypes(){
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/lvPlan/compactibleEventTypes',
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
@@ -1,25 +0,0 @@
|
||||
/**
|
||||
* 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 {
|
||||
getBasicUserAttributesForLvPlanDisplay(uid) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/OtherLvPlan/getBasicUserAttributesForLvPlanDisplay/${uid}`,
|
||||
};
|
||||
},
|
||||
};
|
||||
+103
-146
@@ -1,201 +1,158 @@
|
||||
import FhcSearchbar from "../components/searchbar/searchbar.js";
|
||||
import CisMenu from "../components/Cis/Menu.js";
|
||||
import PluginsPhrasen from "../plugins/Phrasen.js";
|
||||
import PluginsPhrasen from '../plugins/Phrasen.js';
|
||||
import ApiSearchbar from '../api/factory/searchbar.js';
|
||||
import Theme from "../plugins/Theme.js";
|
||||
|
||||
import ApiSearchbar from "../api/factory/searchbar.js";
|
||||
import ApiLvPlan from "../api/factory/lvPlan.js";
|
||||
|
||||
const app = Vue.createApp({
|
||||
name: "CisApp",
|
||||
components: {
|
||||
FhcSearchbar,
|
||||
CisMenu,
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
searchbaroptions: {
|
||||
name: 'CisApp',
|
||||
components: {
|
||||
FhcSearchbar,
|
||||
CisMenu
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
searchbaroptions: {
|
||||
origin: "cis",
|
||||
cssclass: "",
|
||||
calcheightonly: true,
|
||||
types: {
|
||||
employee: Vue.computed(() =>
|
||||
this.$p.t("search/type_employee"),
|
||||
),
|
||||
student: Vue.computed(() =>
|
||||
this.$p.t("search/type_student"),
|
||||
),
|
||||
employee: Vue.computed(() => this.$p.t("search/type_employee")),
|
||||
student: Vue.computed(() => this.$p.t("search/type_student")),
|
||||
room: Vue.computed(() => this.$p.t("search/type_room")),
|
||||
organisationunit: Vue.computed(() =>
|
||||
this.$p.t("search/type_organisationunit"),
|
||||
),
|
||||
organisationunit: Vue.computed(() => this.$p.t("search/type_organisationunit")),
|
||||
cms: Vue.computed(() => this.$p.t("search/type_cms")),
|
||||
dms: Vue.computed(() => this.$p.t("search/type_dms")),
|
||||
dms: Vue.computed(() => this.$p.t("search/type_dms"))
|
||||
},
|
||||
actions: {
|
||||
employee: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
action: function (data) {
|
||||
return (
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router +
|
||||
"/Cis/Profil/View/" +
|
||||
data.uid
|
||||
);
|
||||
},
|
||||
actions: {
|
||||
employee: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
action: function(data) {
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router+
|
||||
"/Cis/Profil/View/"+data.uid;
|
||||
}
|
||||
},
|
||||
childactions: [],
|
||||
childactions: []
|
||||
},
|
||||
student: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
action: function (data) {
|
||||
return (
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router +
|
||||
"/Cis/Profil/View/" +
|
||||
data.uid
|
||||
);
|
||||
},
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router +
|
||||
"/Cis/Profil/View/" + data.uid;
|
||||
|
||||
}
|
||||
},
|
||||
childactions: [],
|
||||
childactions: []
|
||||
},
|
||||
room: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
renderif: function (data) {
|
||||
if (data.content_id === null) {
|
||||
room: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
renderif: function(data) {
|
||||
if(data.content_id === null){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
action: function (data) {
|
||||
const link =
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
action: function(data) {
|
||||
const link= FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router +
|
||||
"/CisVue/Cms/content/" +
|
||||
data.content_id;
|
||||
'/CisVue/Cms/content/' + data.content_id;
|
||||
return link;
|
||||
},
|
||||
},
|
||||
childactions: [
|
||||
{
|
||||
label: "LV-Plan",
|
||||
icon: "fas fa-bookmark",
|
||||
type: "link",
|
||||
action: function (data) {
|
||||
const link =
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
}
|
||||
},
|
||||
childactions: [
|
||||
{
|
||||
label: "LV-Plan",
|
||||
icon: "fas fa-bookmark",
|
||||
type: "link",
|
||||
action: function(data) {
|
||||
const link = FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router +
|
||||
"/CisVue/Cms/getRoomInformation/" +
|
||||
data.ort_kurzbz;
|
||||
'/CisVue/Cms/getRoomInformation/' + data.ort_kurzbz;
|
||||
return link;
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "Rauminformation",
|
||||
icon: "fas fa-info-circle",
|
||||
type: "link",
|
||||
renderif: function (data) {
|
||||
if (data.content_id === null) {
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "Rauminformation",
|
||||
icon: "fas fa-info-circle",
|
||||
type: "link",
|
||||
renderif: function(data) {
|
||||
if(data.content_id === null){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
action: function (data) {
|
||||
const link =
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
},
|
||||
action: function(data) {
|
||||
const link= FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router +
|
||||
"/CisVue/Cms/content/" +
|
||||
data.content_id;
|
||||
'/CisVue/Cms/content/' + data.content_id;
|
||||
return link;
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
organisationunit: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
renderif: function (data) {
|
||||
if (data.mailgroup) {
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
organisationunit: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
renderif: function(data) {
|
||||
if(data.mailgroup) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
action: function (data) {
|
||||
const link = "mailto:" + data.mailgroup;
|
||||
action: function(data) {
|
||||
const link = 'mailto:' + data.mailgroup;
|
||||
return link;
|
||||
},
|
||||
},
|
||||
childactions: [],
|
||||
},
|
||||
}
|
||||
},
|
||||
childactions: []
|
||||
},
|
||||
cms: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
action: function (data) {
|
||||
const link =
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
const link = FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router +
|
||||
"/CisVue/Cms/content/" +
|
||||
data.content_id;
|
||||
'/CisVue/Cms/content/' + data.content_id;
|
||||
return link;
|
||||
},
|
||||
}
|
||||
},
|
||||
childactions: [],
|
||||
childactions: []
|
||||
},
|
||||
dms: {
|
||||
defaultaction: {
|
||||
type: "link",
|
||||
action: function (data) {
|
||||
const link =
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
"cms/dms.php?id=" +
|
||||
data.dms_id;
|
||||
const link = FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
'cms/dms.php?id=' + data.dms_id;
|
||||
return link;
|
||||
},
|
||||
}
|
||||
},
|
||||
childactions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
searchfunction: function (searchsettings) {
|
||||
return this.$api.call(ApiSearchbar.searchCis(searchsettings));
|
||||
childactions: []
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isMobile() {
|
||||
const smallScreen = window.matchMedia("(max-width: 767px)").matches;
|
||||
const touchCapable = ("ontouchstart" in window) || navigator.maxTouchPoints > 0;
|
||||
return smallScreen;// && touchCapable;
|
||||
},
|
||||
},
|
||||
async mounted() {
|
||||
const openOtherLvPlanAction = {
|
||||
label: Vue.computed(() => this.$p.t("lehre/stundenplan")),
|
||||
icon: "fas fa-calendar-days",
|
||||
type: "link",
|
||||
action: function (data) {
|
||||
const uid = JSON.parse(data.data).uid;
|
||||
const link =
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router +
|
||||
"/Cis/OtherLvPlan/" +
|
||||
uid;
|
||||
return link;
|
||||
},
|
||||
};
|
||||
let checkPermissionOtherLvPlanResult = await this.$api.call(
|
||||
ApiLvPlan.checkPermissionOtherLvPlan(),
|
||||
);
|
||||
if (
|
||||
checkPermissionOtherLvPlanResult.meta.status === "success" &&
|
||||
checkPermissionOtherLvPlanResult.data
|
||||
) {
|
||||
this.searchbaroptions.actions.employee.childactions.push(
|
||||
openOtherLvPlanAction,
|
||||
);
|
||||
this.searchbaroptions.actions.student.childactions.push(
|
||||
openOtherLvPlanAction,
|
||||
);
|
||||
provide() {
|
||||
return {
|
||||
isMobile: this.isMobile
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
searchfunction: function(searchsettings) {
|
||||
return this.$api.call(ApiSearchbar.searchCis(searchsettings));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
FhcApps.makeExtendable(app);
|
||||
@@ -203,9 +160,9 @@ FhcApps.makeExtendable(app);
|
||||
app.use(primevue.config.default, {
|
||||
zIndex: {
|
||||
overlay: 9000,
|
||||
tooltip: 8000,
|
||||
},
|
||||
});
|
||||
tooltip: 8000
|
||||
}
|
||||
})
|
||||
app.use(PluginsPhrasen);
|
||||
app.use(Theme);
|
||||
app.mount("#cis-header");
|
||||
app.mount('#cis-header');
|
||||
|
||||
@@ -11,21 +11,18 @@ import Raumsuche from "../../components/Cis/Raumsuche/Raumsuche.js";
|
||||
import CmsNews from "../../components/Cis/Cms/News.js";
|
||||
import CmsContent from "../../components/Cis/Cms/Content.js";
|
||||
import Info from "../../components/Cis/Mylv/Semester/Studiengang/Lv/Info.js";
|
||||
import RoomInformation, {DEFAULT_MODE_RAUMINFO_DESKTOP, DEFAULT_MODE_RAUMINFO_MOBILE} from "../../components/Cis/Mylv/RoomInformation.js";
|
||||
import RoomInformation, {DEFAULT_MODE_RAUMINFO} from "../../components/Cis/Mylv/RoomInformation.js";
|
||||
import AbgabetoolStudent from "../../components/Cis/Abgabetool/AbgabetoolStudent.js";
|
||||
import AbgabetoolMitarbeiter from "../../components/Cis/Abgabetool/AbgabetoolMitarbeiter.js";
|
||||
import AbgabetoolAssistenz from "../../components/Cis/Abgabetool/AbgabetoolAssistenz.js";
|
||||
import DeadlineOverview from "../../components/Cis/Abgabetool/DeadlineOverview.js";
|
||||
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 ApiRenderers from '../../api/factory/renderers.js';
|
||||
import ApiRouteInfo from '../../api/factory/routeinfo.js';
|
||||
import {capitalize} from "../../helpers/StringHelpers.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;
|
||||
|
||||
const router = VueRouter.createRouter({
|
||||
history: VueRouter.createWebHistory(`/${ciPath}`),
|
||||
@@ -88,7 +85,7 @@ const router = VueRouter.createRouter({
|
||||
name: "RoomInformation",
|
||||
params: { // in this case always populate other params since they are not optional
|
||||
ort_kurzbz: to.params.ort_kurzbz,
|
||||
mode: isMobile ? DEFAULT_MODE_RAUMINFO_MOBILE : DEFAULT_MODE_RAUMINFO_DESKTOP,
|
||||
mode: DEFAULT_MODE_RAUMINFO,
|
||||
focus_date: new Date().toISOString().split("T")[0]
|
||||
},
|
||||
};
|
||||
@@ -105,7 +102,7 @@ const router = VueRouter.createRouter({
|
||||
const mode = route.params.mode &&
|
||||
validModes.includes(route.params.mode.charAt(0).toUpperCase() + route.params.mode.slice(1).toLowerCase())
|
||||
? route.params.mode.charAt(0).toUpperCase() + route.params.mode.slice(1).toLowerCase()
|
||||
: (isMobile ? DEFAULT_MODE_RAUMINFO_MOBILE : DEFAULT_MODE_RAUMINFO_DESKTOP);
|
||||
: DEFAULT_MODE_RAUMINFO;
|
||||
|
||||
// default to today date if not provided
|
||||
const d = new Date(route.params.focus_date)
|
||||
@@ -127,7 +124,7 @@ const router = VueRouter.createRouter({
|
||||
next({
|
||||
name: "RoomInformation",
|
||||
params: {
|
||||
mode: to.params.mode || (isMobile ? DEFAULT_MODE_RAUMINFO_MOBILE : DEFAULT_MODE_RAUMINFO_DESKTOP),
|
||||
mode: to.params.mode || DEFAULT_MODE_RAUMINFO,
|
||||
focus_date: to.params.focus_date || new Date().toISOString().split("T")[0],
|
||||
ort_kurzbz: route.params.ort_kurzbz
|
||||
}
|
||||
@@ -200,26 +197,6 @@ const router = VueRouter.createRouter({
|
||||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
path: `/Cis/StgOrgLvPlan/:mode?/:focus_date?/:stgkz?/:sem?/:verband?/:gruppe?`,
|
||||
name: 'StgOrgLvPlan',
|
||||
component: StgOrgLvPlan,
|
||||
props(route) {
|
||||
return {
|
||||
propsViewData: route.params
|
||||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
path: `/Cis/OtherLvPlan/:otherUid/:mode?/:focus_date?`,
|
||||
name: "OtherLvPlan",
|
||||
component: OtherLvPlan,
|
||||
props(route) {
|
||||
return {
|
||||
propsViewData: route.params
|
||||
};
|
||||
}
|
||||
},
|
||||
{
|
||||
path: `/Cis4`,
|
||||
name: 'Cis4',
|
||||
@@ -261,13 +238,13 @@ const app = Vue.createApp({
|
||||
const smallScreen = window.matchMedia("(max-width: 767px)").matches;
|
||||
const touchCapable = ("ontouchstart" in window) || navigator.maxTouchPoints > 0;
|
||||
return smallScreen;// && touchCapable;
|
||||
}
|
||||
},
|
||||
},
|
||||
provide() {
|
||||
return { // provide injectable & watchable language property
|
||||
language: Vue.computed(() => this.$p.user_language),
|
||||
renderers: Vue.computed(() => this.renderers),
|
||||
isMobile: this.isMobile
|
||||
isMobile: this.isMobile,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -306,6 +283,7 @@ const app = Vue.createApp({
|
||||
}
|
||||
},
|
||||
async created(){
|
||||
|
||||
await this.$api
|
||||
.call(ApiRenderers.loadRenderers())
|
||||
.then(res => res.data)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import LineEvent from "./Line/Event.js";
|
||||
import LineBackground from "./Line/Background.js";
|
||||
import LineEvent from './Line/Event.js';
|
||||
import LineBackground from './Line/Background.js';
|
||||
|
||||
/**
|
||||
* TODO(chris):
|
||||
@@ -10,117 +10,54 @@ export default {
|
||||
name: "GridLine",
|
||||
components: {
|
||||
LineEvent,
|
||||
LineBackground,
|
||||
LineBackground
|
||||
},
|
||||
inject: {
|
||||
axisRow: "axisRow"
|
||||
},
|
||||
inject: ["axisRow", "shouldCompactEvents", "compactibleEventTypes"],
|
||||
props: {
|
||||
date: {
|
||||
type: luxon.DateTime,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
start: {
|
||||
type: luxon.DateTime,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
end: {
|
||||
type: luxon.DateTime,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
events: {
|
||||
type: Array,
|
||||
default: [],
|
||||
default: []
|
||||
},
|
||||
backgrounds: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
default: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
formattedEvents() {
|
||||
let formattedEvents = this.events.map((event) => {
|
||||
event.rows = [1, -1];
|
||||
eventsWithRowInfo() {
|
||||
const events = [];
|
||||
this.events.forEach(event => {
|
||||
const rows = [1, -1];
|
||||
if (event.startsHere) {
|
||||
event.rows[0] =
|
||||
"t_" + event.start.diff(this.date).toMillis();
|
||||
rows[0] = 't_' + event.start.diff(this.date).toMillis();
|
||||
}
|
||||
if (event.endsHere) {
|
||||
event.rows[1] = "t_" + event.end.diff(this.date).toMillis();
|
||||
rows[1] = 't_' + event.end.diff(this.date).toMillis();
|
||||
}
|
||||
|
||||
return event;
|
||||
});
|
||||
|
||||
if (this.shouldCompactEvents && this.compactibleEventTypes?.length) {
|
||||
formattedEvents =
|
||||
this.compactEvents(formattedEvents, this.compactibleEventTypes);
|
||||
}
|
||||
|
||||
return formattedEvents;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
compactEvents(events, compactibleEventTypes) {
|
||||
let formattedEvents = events
|
||||
.filter(
|
||||
(event) =>
|
||||
!compactibleEventTypes.includes(event.type),
|
||||
)
|
||||
.map((event) => {
|
||||
event.display = "default";
|
||||
return event;
|
||||
events.push({
|
||||
...event,
|
||||
rows
|
||||
});
|
||||
let eventsToBeCompacted = events.filter((event) =>
|
||||
compactibleEventTypes.includes(event.type),
|
||||
);
|
||||
let compactedEvents = [];
|
||||
|
||||
eventsToBeCompacted.forEach((event) => {
|
||||
let existingCompactedEvent = compactedEvents.find(
|
||||
(compactedEvent) =>
|
||||
event.rows[0] === compactedEvent.rows[0] &&
|
||||
event.rows[1] === compactedEvent.rows[1],
|
||||
);
|
||||
|
||||
if (!existingCompactedEvent) {
|
||||
compactedEvents.push({
|
||||
events: [
|
||||
{
|
||||
farbe: event.orig.farbe,
|
||||
},
|
||||
],
|
||||
rows: event.rows,
|
||||
});
|
||||
} else {
|
||||
existingCompactedEvent.events.push({
|
||||
farbe: event.orig.farbe,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
compactedEvents.forEach((compactedEvent) => {
|
||||
if (compactedEvent.events.length < 4) {
|
||||
formattedEvents.push({
|
||||
display: "compacted",
|
||||
...compactedEvent,
|
||||
});
|
||||
} else {
|
||||
formattedEvents.push({
|
||||
display: "compacted",
|
||||
events: compactedEvent.events.slice(0, 3),
|
||||
rows: compactedEvent.rows,
|
||||
});
|
||||
formattedEvents.push({
|
||||
display: "compactedExtra",
|
||||
events: compactedEvent.events.slice(3),
|
||||
rows: compactedEvent.rows,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return formattedEvents;
|
||||
},
|
||||
return events;
|
||||
}
|
||||
},
|
||||
template: /* html */ `
|
||||
template: /* html */`
|
||||
<div
|
||||
class="fhc-calendar-base-grid-line"
|
||||
style="position:relative;display:grid;grid-auto-flow:dense"
|
||||
@@ -132,37 +69,17 @@ export default {
|
||||
:end="end"
|
||||
:background="bg"
|
||||
></line-background>
|
||||
<template v-for="(event, i) in formattedEvents" :key="i">
|
||||
<line-event
|
||||
v-if="!event.display || event.display === 'default'"
|
||||
:style="'grid-' + axisRow + ': ' + event.rows.join('/')"
|
||||
:event="event"
|
||||
>
|
||||
<template v-slot="slot">
|
||||
<slot name="event" v-bind="slot" />
|
||||
</template>
|
||||
</line-event>
|
||||
<div
|
||||
v-else-if="event.display === 'compacted'"
|
||||
:style="'grid-' + axisRow + ': ' + event.rows.join('/')"
|
||||
class="d-flex flex-row justify-content-center gap-1 align-items-center"
|
||||
>
|
||||
<i
|
||||
v-for="(subEvent, subEventIndex) in event.events"
|
||||
:key="subEventIndex"
|
||||
class="fa-solid fa-circle fa-2xs"
|
||||
:style="subEvent.farbe ? {color: '#' + subEvent.farbe} : {}"
|
||||
></i>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="event.display === 'compactedExtra'"
|
||||
:style="'grid-' + axisRow + ': ' + event.rows.join('/')"
|
||||
class="w-100 d-flex flex-row justify-content-center"
|
||||
>
|
||||
{{"+" + event.events.length}}
|
||||
</div>
|
||||
</template>
|
||||
<line-event
|
||||
v-for="(event, i) in eventsWithRowInfo"
|
||||
:key="i"
|
||||
:style="'grid-' + axisRow + ': ' + event.rows.join('/')"
|
||||
:event="event"
|
||||
>
|
||||
<template v-slot="slot">
|
||||
<slot name="event" v-bind="slot" />
|
||||
</template>
|
||||
</line-event>
|
||||
<slot name="dropzone" />
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
`
|
||||
}
|
||||
|
||||
@@ -1,159 +1,122 @@
|
||||
import FhcCalendar from "./Base.js";
|
||||
|
||||
import ApiLvPlan from "../../api/factory/lvPlan.js";
|
||||
import ApiLvPlan from '../../api/factory/lvPlan.js';
|
||||
|
||||
import { useEventLoader } from "../../composables/EventLoader.js";
|
||||
import { useEventLoader } from '../../composables/EventLoader.js';
|
||||
|
||||
import ModeDay from "./Mode/Day.js";
|
||||
import ModeWeek from "./Mode/Week.js";
|
||||
import ModeMonth from "./Mode/Month.js";
|
||||
import ModeList from "./Mode/List.js";
|
||||
import ModeDay from './Mode/Day.js';
|
||||
import ModeWeek from './Mode/Week.js';
|
||||
import ModeMonth from './Mode/Month.js';
|
||||
|
||||
export default {
|
||||
name: "CalendarLvPlan",
|
||||
components: {
|
||||
FhcCalendar,
|
||||
FhcCalendar
|
||||
},
|
||||
inject: ["renderers", "isMobile"],
|
||||
inject: [
|
||||
"renderers"
|
||||
],
|
||||
props: {
|
||||
timezone: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
date: {
|
||||
type: [Date, String, Number, luxon.DateTime],
|
||||
default: luxon.DateTime.local(),
|
||||
default: luxon.DateTime.local()
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: "Day",
|
||||
default: 'Week'
|
||||
},
|
||||
getPromiseFunc: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
shouldCompactEvents: Vue.computed(
|
||||
() => this.$props.mode === "Month" && this.isMobile,
|
||||
),
|
||||
compactibleEventTypes: Vue.computed(
|
||||
() => this.compactibleEventTypes,
|
||||
),
|
||||
};
|
||||
},
|
||||
emits: ["update:date", "update:mode", "update:range"],
|
||||
emits: [
|
||||
"update:date",
|
||||
"update:mode",
|
||||
"update:range"
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
modes: {
|
||||
day: Vue.markRaw(ModeDay),
|
||||
week: Vue.markRaw(ModeWeek),
|
||||
month: Vue.markRaw(ModeMonth)
|
||||
},
|
||||
modeOptions: {
|
||||
day: {
|
||||
emptyMessage: Vue.computed(() =>
|
||||
this.$p.t("lehre/noLvFound"),
|
||||
),
|
||||
emptyMessageDetails: Vue.computed(() =>
|
||||
this.$p.t("lehre/noLvFound"),
|
||||
),
|
||||
emptyMessage: Vue.computed(() => this.$p.t('lehre/noLvFound')),
|
||||
emptyMessageDetails: Vue.computed(() => this.$p.t('lehre/noLvFound'))
|
||||
},
|
||||
week: {
|
||||
collapseEmptyDays: false,
|
||||
},
|
||||
list: {
|
||||
length: 7,
|
||||
},
|
||||
collapseEmptyDays: false
|
||||
}
|
||||
},
|
||||
teachingunits: null,
|
||||
compactibleEventTypes: [],
|
||||
teachingunits: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
backgrounds() {
|
||||
let now = luxon.DateTime.now().setZone(this.timezone);
|
||||
|
||||
if (this.mode == "Month")
|
||||
if (this.mode == 'Month')
|
||||
return [
|
||||
{
|
||||
class: "background-past",
|
||||
end: now.startOf("day"),
|
||||
},
|
||||
class: 'background-past',
|
||||
end: now.startOf('day')
|
||||
}
|
||||
];
|
||||
|
||||
return [
|
||||
{
|
||||
class: "background-past",
|
||||
class: 'background-past',
|
||||
end: now,
|
||||
label: now.startOf("minute").toISOTime({
|
||||
suppressSeconds: true,
|
||||
includeOffset: false,
|
||||
}),
|
||||
},
|
||||
label: now.startOf('minute').toISOTime({ suppressSeconds: true, includeOffset: false })
|
||||
}
|
||||
];
|
||||
},
|
||||
modes() {
|
||||
let modes = {
|
||||
day: Vue.markRaw(ModeDay),
|
||||
month: Vue.markRaw(ModeMonth),
|
||||
};
|
||||
if (this.isMobile) {
|
||||
modes.list = Vue.markRaw(ModeList);
|
||||
} else {
|
||||
modes.week = Vue.markRaw(ModeWeek);
|
||||
}
|
||||
|
||||
return modes;
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
eventStyle(event) {
|
||||
if (!event.farbe) return undefined;
|
||||
return "--event-bg:#" + event.farbe;
|
||||
if (!event.farbe)
|
||||
return undefined;
|
||||
return '--event-bg:#' + event.farbe;
|
||||
},
|
||||
updateRange(rangeInterval) {
|
||||
this.rangeInterval = rangeInterval;
|
||||
this.$emit("update:range", rangeInterval);
|
||||
},
|
||||
resetEventLoader() {
|
||||
this.reset();
|
||||
},
|
||||
async getStunden() {
|
||||
let stundenResponse = await this.$api.call(ApiLvPlan.getStunden());
|
||||
this.teachingunits = stundenResponse.data.map((el) => ({
|
||||
id: el.stunde,
|
||||
start: el.beginn,
|
||||
end: el.ende,
|
||||
}));
|
||||
},
|
||||
async getCompactibleEventTypes() {
|
||||
let compactibleEventTypesResponse = await this.$api.call(
|
||||
ApiLvPlan.getCompactibleEventTypes(),
|
||||
);
|
||||
this.compactibleEventTypes = compactibleEventTypesResponse.data;
|
||||
},
|
||||
this.$emit('update:range', rangeInterval);
|
||||
}
|
||||
},
|
||||
setup(props, context) {
|
||||
const rangeInterval = Vue.ref(null);
|
||||
|
||||
const { events, lv } = useEventLoader(rangeInterval, props.getPromiseFunc);
|
||||
|
||||
const { events, lv, reset } = useEventLoader(
|
||||
rangeInterval,
|
||||
props.getPromiseFunc,
|
||||
);
|
||||
|
||||
Vue.watch(lv, (newValue) => {
|
||||
context.emit("update:lv", newValue);
|
||||
Vue.watch(lv, newValue => {
|
||||
context.emit('update:lv', newValue);
|
||||
});
|
||||
|
||||
return {
|
||||
rangeInterval,
|
||||
events,
|
||||
lv,
|
||||
reset,
|
||||
lv
|
||||
};
|
||||
},
|
||||
async created() {
|
||||
await this.getStunden();
|
||||
await this.getCompactibleEventTypes();
|
||||
created() {
|
||||
this.$api
|
||||
.call(ApiLvPlan.getStunden())
|
||||
.then(res => {
|
||||
return this.teachingunits = res.data.map(el => ({
|
||||
id: el.stunde,
|
||||
start: el.beginn,
|
||||
end: el.ende
|
||||
}));
|
||||
});
|
||||
},
|
||||
template: /* html */ `
|
||||
template: /* html */`
|
||||
<fhc-calendar
|
||||
ref="calendar"
|
||||
class="fhc-calendar-lvplan"
|
||||
@@ -173,13 +136,6 @@ export default {
|
||||
>
|
||||
<template v-slot="{ event, mode }">
|
||||
<div
|
||||
v-if="!event"
|
||||
class="h-100 d-flex justify-content-center align-items-center"
|
||||
>
|
||||
{{ $p.t('lehre/noLvFound') }}
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
:class="'event-type-' + event.type + ' ' + mode + 'PageContainer'"
|
||||
:type="mode == 'day' ? 'button' : undefined"
|
||||
:style="eventStyle(event)"
|
||||
@@ -204,5 +160,5 @@ export default {
|
||||
<template #actions>
|
||||
<slot />
|
||||
</template>
|
||||
</fhc-calendar>`,
|
||||
};
|
||||
</fhc-calendar>`
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ export default {
|
||||
mounted() {
|
||||
this.$emit('update:range', this.range);
|
||||
},
|
||||
template: /*html*/ `
|
||||
template: `
|
||||
<div
|
||||
class="fhc-calendar-mode-list flex-grow-1 position-relative"
|
||||
@cal-click-default.capture="handleClickDefaults"
|
||||
|
||||
@@ -3,8 +3,7 @@ import FhcCalendar from "../../Calendar/LvPlan.js";
|
||||
import ApiLvPlan from '../../../api/factory/lvPlan.js';
|
||||
import ApiAuthinfo from '../../../api/factory/authinfo.js';
|
||||
|
||||
export const DEFAULT_MODE_LVPLAN_MOBILE = 'List';
|
||||
export const DEFAULT_MODE_LVPLAN_DESKTOP = 'Week';
|
||||
export const DEFAULT_MODE_LVPLAN = 'Week'
|
||||
|
||||
export default {
|
||||
name: 'LvPlanLehrveranstaltung',
|
||||
@@ -20,7 +19,6 @@ export default {
|
||||
lv: null
|
||||
};
|
||||
},
|
||||
inject: ["isMobile"],
|
||||
computed:{
|
||||
currentDay() {
|
||||
if (!this.propsViewData?.focus_date || isNaN(new Date(this.propsViewData?.focus_date)))
|
||||
@@ -28,13 +26,8 @@ export default {
|
||||
return this.propsViewData?.focus_date;
|
||||
},
|
||||
currentMode() {
|
||||
let validModes = ['day', 'month'];
|
||||
validModes.push(this.isMobile ? 'list' : 'week');
|
||||
|
||||
const defaultMode = this.isMobile ? DEFAULT_MODE_LVPLAN_MOBILE : DEFAULT_MODE_LVPLAN_DESKTOP;
|
||||
|
||||
if (!this.propsViewData?.mode || !validModes.includes(this.propsViewData?.mode.toLowerCase()))
|
||||
return defaultMode;
|
||||
if (!this.propsViewData?.mode || !['day', 'week', 'month'].includes(this.propsViewData?.mode.toLowerCase()))
|
||||
return DEFAULT_MODE_LVPLAN;
|
||||
return this.propsViewData?.mode;
|
||||
},
|
||||
currentLv() {
|
||||
|
||||
@@ -3,8 +3,7 @@ import FhcCalendar from "../../Calendar/LvPlan.js";
|
||||
import ApiLvPlan from '../../../api/factory/lvPlan.js';
|
||||
import ApiAuthinfo from '../../../api/factory/authinfo.js';
|
||||
|
||||
export const DEFAULT_MODE_LVPLAN_MOBILE = 'List';
|
||||
export const DEFAULT_MODE_LVPLAN_DESKTOP = 'Week';
|
||||
export const DEFAULT_MODE_LVPLAN = 'Week'
|
||||
|
||||
export default {
|
||||
name: 'LvPlan',
|
||||
@@ -25,14 +24,12 @@ export default {
|
||||
lv: null
|
||||
};
|
||||
},
|
||||
inject: ["isMobile"],
|
||||
computed:{
|
||||
currentDay() {
|
||||
return this.propsViewData?.focus_date || luxon.DateTime.now().setZone(this.viewData.timezone).toISODate();
|
||||
},
|
||||
currentMode() {
|
||||
const defaultMode = this.isMobile ? DEFAULT_MODE_LVPLAN_MOBILE : DEFAULT_MODE_LVPLAN_DESKTOP;
|
||||
return this.propsViewData?.mode || defaultMode;
|
||||
return this.propsViewData?.mode || DEFAULT_MODE_LVPLAN;
|
||||
},
|
||||
downloadLinks() {
|
||||
if (!this.studiensemester_start || !this.studiensemester_ende || !this.uid)
|
||||
|
||||
@@ -1,261 +0,0 @@
|
||||
import FormForm from "../../Form/Form.js";
|
||||
import FormInput from "../../Form/Input.js";
|
||||
import FhcCalendar from "../../Calendar/LvPlan.js";
|
||||
|
||||
import ApiLvPlan from "../.././../api/factory/lvPlan.js";
|
||||
import ApiOtherLvPlan from "../.././../api/factory/otherLvPlan.js";
|
||||
import ApiAuthinfo from "../../../api/factory/authinfo.js";
|
||||
|
||||
export const DEFAULT_MODE_LVPLAN_DESKTOP = "Week";
|
||||
export const DEFAULT_MODE_LVPLAN_MOBILE = "List";
|
||||
|
||||
export default {
|
||||
name: "OtherLvPlan",
|
||||
components: {
|
||||
FormForm,
|
||||
FormInput,
|
||||
FhcCalendar,
|
||||
},
|
||||
props: {
|
||||
viewData: Object,
|
||||
propsViewData: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
localProps: {},
|
||||
studiensemester_kurzbz: null,
|
||||
studiensemester_start: null,
|
||||
studiensemester_ende: null,
|
||||
isOtherPersonMitarbeiter: false,
|
||||
isOtherPersonStudent: false,
|
||||
currentStgBezeichnung: null,
|
||||
listVerband: [],
|
||||
listGroup: [],
|
||||
rangeIntervalFirst: null,
|
||||
otherPersonData: {
|
||||
fullName: "",
|
||||
photo: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
inject: ["isMobile"],
|
||||
computed: {
|
||||
currentDay() {
|
||||
if (
|
||||
!this.propsViewData?.focus_date ||
|
||||
isNaN(new Date(this.propsViewData?.focus_date))
|
||||
)
|
||||
return luxon.DateTime.now()
|
||||
.setZone(this.viewData.timezone)
|
||||
.toISODate();
|
||||
return this.propsViewData?.focus_date;
|
||||
},
|
||||
currentMode() {
|
||||
let validModes = ["day", "month"];
|
||||
validModes.push(this.isMobile ? "list" : "week");
|
||||
|
||||
const defaultMode = this.isMobile
|
||||
? DEFAULT_MODE_LVPLAN_MOBILE
|
||||
: DEFAULT_MODE_LVPLAN_DESKTOP;
|
||||
|
||||
if (
|
||||
!this.propsViewData?.mode ||
|
||||
!validModes.includes(this.propsViewData?.mode.toLowerCase())
|
||||
)
|
||||
return defaultMode;
|
||||
return this.propsViewData?.mode;
|
||||
},
|
||||
downloadLinks() {
|
||||
if (
|
||||
!this.studiensemester_start ||
|
||||
!this.studiensemester_ende ||
|
||||
!this.propsViewData.otherUid
|
||||
)
|
||||
return false;
|
||||
|
||||
const type = this.isOtherPersonStudent
|
||||
? "student"
|
||||
: this.isOtherPersonMitarbeiter
|
||||
? "lektor"
|
||||
: null;
|
||||
|
||||
if (!type) return;
|
||||
|
||||
const opts = { zone: this.viewData.timezone };
|
||||
const start = luxon.DateTime.fromISO(
|
||||
this.studiensemester_start,
|
||||
opts,
|
||||
).toUnixInteger();
|
||||
const ende = luxon.DateTime.fromISO(
|
||||
this.studiensemester_ende,
|
||||
opts,
|
||||
).toUnixInteger();
|
||||
|
||||
const download_link =
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
"cis/private/lvplan/stpl_kalender.php" +
|
||||
"?type=" +
|
||||
type +
|
||||
"&pers_uid=" +
|
||||
this.propsViewData.otherUid +
|
||||
"&begin=" +
|
||||
start +
|
||||
"&ende=" +
|
||||
ende;
|
||||
|
||||
return [
|
||||
{
|
||||
title: "excel",
|
||||
icon: "fa-solid fa-file-excel",
|
||||
link: download_link + "&format=excel",
|
||||
},
|
||||
{
|
||||
title: "csv",
|
||||
icon: "fa-solid fa-file-csv",
|
||||
link: download_link + "&format=csv",
|
||||
},
|
||||
{
|
||||
title: "ical1",
|
||||
icon: "fa-regular fa-calendar",
|
||||
link: download_link + "&format=ical&version=1&target=ical",
|
||||
},
|
||||
{
|
||||
title: "ical2",
|
||||
icon: "fa-regular fa-calendar",
|
||||
link: download_link + "&format=ical&version=2&target=ical",
|
||||
},
|
||||
];
|
||||
},
|
||||
get_image_base64_src: function () {
|
||||
if (!this.otherPersonData.photo?.length) {
|
||||
return "";
|
||||
}
|
||||
return "data:image/jpeg;base64," + this.otherPersonData.photo;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
"propsViewData.otherUid": {
|
||||
handler() {
|
||||
this.$router.go();
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleChangeDate(day, newMode) {
|
||||
return this.handleChangeMode(newMode, day);
|
||||
},
|
||||
handleChangeMode(newMode, day) {
|
||||
const mode = newMode[0].toUpperCase() + newMode.slice(1);
|
||||
const focus_date = day.toISODate();
|
||||
|
||||
this.$router.push({
|
||||
name: "OtherLvPlan",
|
||||
params: {
|
||||
mode,
|
||||
focus_date,
|
||||
},
|
||||
});
|
||||
},
|
||||
updateRange(rangeInterval) {
|
||||
this.$api
|
||||
.call(
|
||||
ApiLvPlan.studiensemesterDateInterval(
|
||||
rangeInterval.end.startOf("week").toISODate(),
|
||||
),
|
||||
)
|
||||
.then((res) => {
|
||||
this.studiensemester_kurzbz =
|
||||
res.data.studiensemester_kurzbz;
|
||||
this.studiensemester_start = res.data.start;
|
||||
this.studiensemester_ende = res.data.ende;
|
||||
});
|
||||
},
|
||||
getPromiseFunc(start, end) {
|
||||
return [
|
||||
this.$api.call(
|
||||
ApiLvPlan.eventsPersonal(
|
||||
start.toISODate(),
|
||||
end.toISODate(),
|
||||
this.propsViewData.otherUid,
|
||||
),
|
||||
),
|
||||
this.$api.call(
|
||||
ApiLvPlan.getLvPlanReservierungen(
|
||||
start.toISODate(),
|
||||
end.toISODate(),
|
||||
this.propsViewData.otherUid,
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
},
|
||||
async created() {
|
||||
const authInfoResponse = await this.$api.call(
|
||||
ApiAuthinfo.getAuthInfo(),
|
||||
);
|
||||
const authId = authInfoResponse.data.uid;
|
||||
if (authId === this.propsViewData.otherUid) {
|
||||
this.$router.push({ name: "MyLvPlan" });
|
||||
}
|
||||
|
||||
const userDataResponse = await this.$api.call(
|
||||
ApiOtherLvPlan.getBasicUserAttributesForLvPlanDisplay(
|
||||
this.propsViewData.otherUid,
|
||||
),
|
||||
);
|
||||
|
||||
const userData = userDataResponse.data;
|
||||
this.isOtherPersonMitarbeiter = !!userData.is_mitarbeiter;
|
||||
this.isOtherPersonStudent = !!userData.is_student;
|
||||
this.otherPersonData.fullName =
|
||||
userData.vorname + " " + userData.nachname;
|
||||
this.otherPersonData.photo = userData.foto;
|
||||
},
|
||||
template: `
|
||||
<div class="d-flex flex-column h-100">
|
||||
<h2>
|
||||
<div class="d-flex flex-row justify-content-between align-items-center">
|
||||
<span>
|
||||
{{ $p.t('lehre/stundenplan') + (studiensemester_kurzbz ? " " + studiensemester_kurzbz : "") }}
|
||||
</span>
|
||||
<div @click="this.$router.push({name: 'ProfilView', params: {uid: propsViewData.otherUid}})" type="button" class="d-flex flex-row align-items-center gap-3">
|
||||
<span v-if="otherPersonData.fullName?.length">
|
||||
{{ otherPersonData.fullName }}
|
||||
</span>
|
||||
<img v-if="otherPersonData.photo?.length" alt="profile picture" class=" img-thumbnail " style=" max-height:60px; " :src="get_image_base64_src"/>
|
||||
</div>
|
||||
</div>
|
||||
</h2>
|
||||
<hr>
|
||||
<fhc-calendar
|
||||
ref="calendar"
|
||||
:timezone="viewData.timezone"
|
||||
:get-promise-func="getPromiseFunc"
|
||||
:date="currentDay"
|
||||
:mode="currentMode"
|
||||
@update:date="handleChangeDate"
|
||||
@update:mode="handleChangeMode"
|
||||
@update:range="updateRange"
|
||||
class="responsive-calendar"
|
||||
>
|
||||
<div
|
||||
v-if="downloadLinks"
|
||||
class="d-flex gap-1 justify-items-start"
|
||||
>
|
||||
<div v-for="{ title, icon, link } in downloadLinks">
|
||||
<a
|
||||
:href="link"
|
||||
:aria-label="title"
|
||||
class="py-1 btn btn-outline-secondary"
|
||||
>
|
||||
<div class="d-flex flex-column">
|
||||
<i aria-hidden="true" :class="icon"></i>
|
||||
<span style="font-size:.5rem">{{ title }}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</fhc-calendar>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
@@ -1,19 +1,18 @@
|
||||
import FhcCalendar from "../../Calendar/LvPlan.js";
|
||||
|
||||
import ApiLvPlan from "../../../api/factory/lvPlan.js";
|
||||
import ApiAuthinfo from "../../../api/factory/authinfo.js";
|
||||
import ApiLvPlan from '../../../api/factory/lvPlan.js';
|
||||
import ApiAuthinfo from '../../../api/factory/authinfo.js';
|
||||
|
||||
export const DEFAULT_MODE_LVPLAN_DESKTOP = "Week";
|
||||
export const DEFAULT_MODE_LVPLAN_MOBILE = "List";
|
||||
export const DEFAULT_MODE_LVPLAN = 'Week'
|
||||
|
||||
export default {
|
||||
name: "LvPlanPersonal",
|
||||
name: 'LvPlanPersonal',
|
||||
components: {
|
||||
FhcCalendar,
|
||||
FhcCalendar
|
||||
},
|
||||
props: {
|
||||
viewData: Object, // NOTE(chris): this is inherited from router-view
|
||||
propsViewData: Object,
|
||||
propsViewData: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -22,152 +21,99 @@ export default {
|
||||
studiensemester_ende: null,
|
||||
uid: null,
|
||||
isMitarbeiter: false,
|
||||
isStudent: false,
|
||||
isStudent: false
|
||||
};
|
||||
},
|
||||
inject: ["isMobile"],
|
||||
computed: {
|
||||
computed:{
|
||||
currentDay() {
|
||||
if (
|
||||
!this.propsViewData?.focus_date ||
|
||||
isNaN(new Date(this.propsViewData?.focus_date))
|
||||
)
|
||||
return luxon.DateTime.now()
|
||||
.setZone(this.viewData.timezone)
|
||||
.toISODate();
|
||||
if (!this.propsViewData?.focus_date || isNaN(new Date(this.propsViewData?.focus_date)))
|
||||
return luxon.DateTime.now().setZone(this.viewData.timezone).toISODate();
|
||||
return this.propsViewData?.focus_date;
|
||||
},
|
||||
currentMode() {
|
||||
let validModes = ["day", "month"];
|
||||
validModes.push(this.isMobile ? "list" : "week");
|
||||
|
||||
const defaultMode = this.isMobile
|
||||
? DEFAULT_MODE_LVPLAN_MOBILE
|
||||
: DEFAULT_MODE_LVPLAN_DESKTOP;
|
||||
|
||||
if (
|
||||
!this.propsViewData?.mode ||
|
||||
!validModes.includes(this.propsViewData?.mode.toLowerCase())
|
||||
)
|
||||
return defaultMode;
|
||||
if (!this.propsViewData?.mode || !['day', 'week', 'month'].includes(this.propsViewData?.mode.toLowerCase()))
|
||||
return DEFAULT_MODE_LVPLAN;
|
||||
return this.propsViewData?.mode;
|
||||
},
|
||||
downloadLinks() {
|
||||
if (
|
||||
!this.studiensemester_start ||
|
||||
!this.studiensemester_ende ||
|
||||
!this.uid
|
||||
)
|
||||
if (!this.studiensemester_start || !this.studiensemester_ende || !this.uid)
|
||||
return false;
|
||||
|
||||
let type = false;
|
||||
type = this.isStudent ? "student" : type;
|
||||
type = this.isMitarbeiter ? "lektor" : type;
|
||||
if (false === type) {
|
||||
type = this.isStudent ? 'student' : type;
|
||||
type = this.isMitarbeiter ? 'lektor' : type;
|
||||
if (false === type)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const opts = { zone: this.viewData.timezone };
|
||||
const start = luxon.DateTime.fromISO(
|
||||
this.studiensemester_start,
|
||||
opts,
|
||||
).toUnixInteger();
|
||||
const ende = luxon.DateTime.fromISO(
|
||||
this.studiensemester_ende,
|
||||
opts,
|
||||
).toUnixInteger();
|
||||
const start = luxon.DateTime
|
||||
.fromISO(this.studiensemester_start, opts)
|
||||
.toUnixInteger();
|
||||
const ende = luxon.DateTime
|
||||
.fromISO(this.studiensemester_ende, opts)
|
||||
.toUnixInteger();
|
||||
|
||||
const download_link =
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
"cis/private/lvplan/stpl_kalender.php" +
|
||||
"?type=" +
|
||||
type +
|
||||
"&pers_uid=" +
|
||||
this.uid +
|
||||
"&begin=" +
|
||||
start +
|
||||
"&ende=" +
|
||||
ende;
|
||||
const download_link = FHC_JS_DATA_STORAGE_OBJECT.app_root
|
||||
+ 'cis/private/lvplan/stpl_kalender.php'
|
||||
+ '?type=' + type
|
||||
+ '&pers_uid=' + this.uid
|
||||
+ '&begin=' + start
|
||||
+ '&ende=' + ende;
|
||||
|
||||
return [
|
||||
{
|
||||
title: "excel",
|
||||
icon: "fa-solid fa-file-excel",
|
||||
link: download_link + "&format=excel",
|
||||
},
|
||||
{
|
||||
title: "csv",
|
||||
icon: "fa-solid fa-file-csv",
|
||||
link: download_link + "&format=csv",
|
||||
},
|
||||
{
|
||||
title: "ical1",
|
||||
icon: "fa-regular fa-calendar",
|
||||
link: download_link + "&format=ical&version=1&target=ical",
|
||||
},
|
||||
{
|
||||
title: "ical2",
|
||||
icon: "fa-regular fa-calendar",
|
||||
link: download_link + "&format=ical&version=2&target=ical",
|
||||
},
|
||||
{ title: "excel", icon: 'fa-solid fa-file-excel', link: download_link + '&format=excel' },
|
||||
{ title: "csv", icon: 'fa-solid fa-file-csv', link: download_link + '&format=csv' },
|
||||
{ title: "ical1", icon: 'fa-regular fa-calendar', link: download_link + '&format=ical&version=1&target=ical' },
|
||||
{ title: "ical2", icon: 'fa-regular fa-calendar', link: download_link + '&format=ical&version=2&target=ical' }
|
||||
];
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChangeDate(day, newMode) {
|
||||
return this.handleChangeMode(newMode, day);
|
||||
},
|
||||
handleChangeMode(newMode, day) {
|
||||
const mode = newMode[0].toUpperCase() + newMode.slice(1);
|
||||
const mode = newMode[0].toUpperCase() + newMode.slice(1)
|
||||
const focus_date = day.toISODate();
|
||||
|
||||
|
||||
this.$router.push({
|
||||
name: "MyLvPlan",
|
||||
params: {
|
||||
mode,
|
||||
focus_date,
|
||||
},
|
||||
focus_date
|
||||
}
|
||||
});
|
||||
},
|
||||
updateRange(rangeInterval) {
|
||||
this.$api
|
||||
.call(
|
||||
ApiLvPlan.studiensemesterDateInterval(
|
||||
rangeInterval.end.startOf("week").toISODate(),
|
||||
),
|
||||
)
|
||||
.then((res) => {
|
||||
this.studiensemester_kurzbz =
|
||||
res.data.studiensemester_kurzbz;
|
||||
.call(ApiLvPlan.studiensemesterDateInterval(
|
||||
rangeInterval.end.startOf('week').toISODate()
|
||||
))
|
||||
.then(res => {
|
||||
this.studiensemester_kurzbz = res.data.studiensemester_kurzbz;
|
||||
this.studiensemester_start = res.data.start;
|
||||
this.studiensemester_ende = res.data.ende;
|
||||
});
|
||||
},
|
||||
getPromiseFunc(start, end) {
|
||||
return [
|
||||
this.$api.call(
|
||||
ApiLvPlan.eventsPersonal(
|
||||
start.toISODate(),
|
||||
end.toISODate(),
|
||||
),
|
||||
),
|
||||
this.$api.call(
|
||||
ApiLvPlan.getLvPlanReservierungen(
|
||||
start.toISODate(),
|
||||
end.toISODate(),
|
||||
),
|
||||
),
|
||||
this.$api.call(ApiLvPlan.eventsPersonal(start.toISODate(), end.toISODate())),
|
||||
this.$api.call(ApiLvPlan.getLvPlanReservierungen(start.toISODate(), end.toISODate()))
|
||||
];
|
||||
},
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$api.call(ApiAuthinfo.getAuthInfo()).then((res) => {
|
||||
this.uid = res.data.uid;
|
||||
this.isMitarbeiter = res.data.isMitarbeiter;
|
||||
this.isStudent = res.data.isStudent;
|
||||
});
|
||||
this.$api
|
||||
.call(ApiAuthinfo.getAuthInfo())
|
||||
.then(res => {
|
||||
this.uid = res.data.uid;
|
||||
this.isMitarbeiter = res.data.isMitarbeiter;
|
||||
this.isStudent = res.data.isStudent;
|
||||
});
|
||||
},
|
||||
template: /*html*/ `
|
||||
template: /*html*/`
|
||||
<div class="cis-lvplan-personal d-flex flex-column h-100">
|
||||
<h2>
|
||||
{{ $p.t('lehre/stundenplan') }}
|
||||
@@ -205,5 +151,5 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
</fhc-calendar>
|
||||
</div>`,
|
||||
</div>`
|
||||
};
|
||||
|
||||
@@ -1,424 +0,0 @@
|
||||
import FormForm from "../../Form/Form.js";
|
||||
import FormInput from "../../Form/Input.js";
|
||||
import FhcCalendar from "../../Calendar/LvPlan.js";
|
||||
|
||||
import ApiLvPlan from "../.././../api/factory/lvPlan.js";
|
||||
import ApiAuthinfo from "../../../api/factory/authinfo.js";
|
||||
|
||||
export const DEFAULT_MODE_LVPLAN_DESKTOP = "Week";
|
||||
export const DEFAULT_MODE_LVPLAN_MOBILE = "List";
|
||||
|
||||
export default {
|
||||
name: "LvPlanStgOrg",
|
||||
components: {
|
||||
FormForm,
|
||||
FormInput,
|
||||
FhcCalendar,
|
||||
},
|
||||
props: {
|
||||
viewData: Object,
|
||||
propsViewData: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
localProps: {},
|
||||
studiensemester_kurzbz: null,
|
||||
studiensemester_start: null,
|
||||
studiensemester_ende: null,
|
||||
uid: null,
|
||||
isMitarbeiter: false,
|
||||
isStudent: false,
|
||||
currentStgBezeichnung: null,
|
||||
formData: {
|
||||
stgkz: null,
|
||||
sem: null,
|
||||
verband: null,
|
||||
gruppe: null,
|
||||
},
|
||||
listStg: [],
|
||||
listSem: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
||||
listVerband: [],
|
||||
listGroup: [],
|
||||
rangeIntervalFirst: null,
|
||||
};
|
||||
},
|
||||
inject: ["isMobile"],
|
||||
computed: {
|
||||
maxSemester() {
|
||||
const currentStg = this.listStg.find(
|
||||
(item) => item.studiengang_kz === this.formData.stgkz,
|
||||
);
|
||||
return currentStg?.max_semester;
|
||||
},
|
||||
currentDay() {
|
||||
if (
|
||||
!this.propsViewData?.focus_date ||
|
||||
isNaN(new Date(this.propsViewData?.focus_date))
|
||||
)
|
||||
return luxon.DateTime.now()
|
||||
.setZone(this.viewData.timezone)
|
||||
.toISODate();
|
||||
return this.propsViewData?.focus_date;
|
||||
},
|
||||
currentMode() {
|
||||
let validModes = ["day", "month"];
|
||||
validModes.push(this.isMobile ? "list" : "week");
|
||||
|
||||
const defaultMode = this.isMobile
|
||||
? DEFAULT_MODE_LVPLAN_MOBILE
|
||||
: DEFAULT_MODE_LVPLAN_DESKTOP;
|
||||
|
||||
if (
|
||||
!this.propsViewData?.mode ||
|
||||
!validModes.includes(this.propsViewData?.mode.toLowerCase())
|
||||
)
|
||||
return defaultMode;
|
||||
return this.propsViewData?.mode;
|
||||
},
|
||||
downloadLinks() {
|
||||
if (
|
||||
!this.studiensemester_start ||
|
||||
!this.studiensemester_ende ||
|
||||
!this.uid
|
||||
)
|
||||
return false;
|
||||
|
||||
let type = false;
|
||||
type = this.isStudent ? "student" : type;
|
||||
type = this.isMitarbeiter ? "lektor" : type;
|
||||
if (false === type) {
|
||||
return;
|
||||
}
|
||||
|
||||
const opts = { zone: this.viewData.timezone };
|
||||
const start = luxon.DateTime.fromISO(
|
||||
this.studiensemester_start,
|
||||
opts,
|
||||
).toUnixInteger();
|
||||
const ende = luxon.DateTime.fromISO(
|
||||
this.studiensemester_ende,
|
||||
opts,
|
||||
).toUnixInteger();
|
||||
|
||||
const download_link =
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
"cis/private/lvplan/stpl_kalender.php" +
|
||||
"?type=" +
|
||||
type +
|
||||
"&pers_uid=" +
|
||||
this.uid +
|
||||
"&begin=" +
|
||||
start +
|
||||
"&ende=" +
|
||||
ende;
|
||||
|
||||
return [
|
||||
{
|
||||
title: "excel",
|
||||
icon: "fa-solid fa-file-excel",
|
||||
link: download_link + "&format=excel",
|
||||
},
|
||||
{
|
||||
title: "csv",
|
||||
icon: "fa-solid fa-file-csv",
|
||||
link: download_link + "&format=csv",
|
||||
},
|
||||
{
|
||||
title: "ical1",
|
||||
icon: "fa-regular fa-calendar",
|
||||
link: download_link + "&format=ical&version=1&target=ical",
|
||||
},
|
||||
{
|
||||
title: "ical2",
|
||||
icon: "fa-regular fa-calendar",
|
||||
link: download_link + "&format=ical&version=2&target=ical",
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
loadLvPlan() {
|
||||
if (!this.formData.stgkz) {
|
||||
this.$fhcAlert.alertError(this.$p.t("LvPlan", "chooseStg"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!this.formData.sem &&
|
||||
(this.formData.verband || this.formData.gruppe)
|
||||
) {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("LvPlan", "error_SemMissing"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.formData.verband && this.formData.gruppe) {
|
||||
this.$fhcAlert.alertError(
|
||||
this.$p.t("LvPlan", "error_VerbandMissing"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const params = {
|
||||
mode: this.currentMode,
|
||||
focus_date: this.currentDay,
|
||||
stgkz: this.formData.stgkz,
|
||||
sem: this.formData.sem,
|
||||
verband: this.formData.verband,
|
||||
gruppe: this.formData.gruppe,
|
||||
};
|
||||
|
||||
//ensure logic: no value after a null value in route
|
||||
if (params.sem == null) {
|
||||
params.verband = null;
|
||||
params.gruppe = null;
|
||||
}
|
||||
if (params.verband == null) {
|
||||
params.gruppe = null;
|
||||
}
|
||||
|
||||
//delete all null values to avoid null in router
|
||||
Object.keys(params).forEach(
|
||||
(key) => params[key] == null && delete params[key],
|
||||
);
|
||||
|
||||
this.$router.push({
|
||||
name: "StgOrgLvPlan",
|
||||
params,
|
||||
});
|
||||
|
||||
this.$refs["calendar"].resetEventLoader();
|
||||
},
|
||||
loadListSem() {
|
||||
this.listSem = [...Array(this.maxSemester).keys()].map(
|
||||
(i) => i + 1,
|
||||
);
|
||||
},
|
||||
loadListVerband() {
|
||||
this.$api
|
||||
.call(
|
||||
ApiLvPlan.getLehrverband(
|
||||
this.formData.stgkz,
|
||||
this.formData.semester,
|
||||
this.formData.verband,
|
||||
),
|
||||
)
|
||||
.then((result) => {
|
||||
const data = result.data;
|
||||
const mappedData = data.map((item) => item.verband);
|
||||
this.listVerband = [
|
||||
...new Set(
|
||||
mappedData.filter(
|
||||
(v) =>
|
||||
v !== null &&
|
||||
v !== undefined &&
|
||||
String(v).trim() !== "",
|
||||
),
|
||||
),
|
||||
].sort();
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
loadListGroup() {
|
||||
this.$api
|
||||
.call(
|
||||
ApiLvPlan.getGruppe(
|
||||
this.formData.stgkz,
|
||||
this.formData.semester,
|
||||
this.formData.verband,
|
||||
),
|
||||
)
|
||||
.then((result) => {
|
||||
const data = result.data;
|
||||
const mappedData = data.map((item) => item.gruppe);
|
||||
this.listGroup = [
|
||||
...new Set(
|
||||
mappedData.filter(
|
||||
(v) =>
|
||||
v !== null &&
|
||||
v !== undefined &&
|
||||
String(v).trim() !== "",
|
||||
),
|
||||
),
|
||||
].sort();
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
handleChangeDate(day, newMode) {
|
||||
return this.handleChangeMode(newMode, day);
|
||||
},
|
||||
handleChangeMode(newMode, day) {
|
||||
const mode = newMode[0].toUpperCase() + newMode.slice(1);
|
||||
const focus_date = day.toISODate();
|
||||
|
||||
this.$router.push({
|
||||
name: "StgOrgLvPlan",
|
||||
params: {
|
||||
mode,
|
||||
focus_date,
|
||||
stgkz: this.formData.stgkz,
|
||||
sem: this.formData.sem,
|
||||
verband: this.formData.verband,
|
||||
gruppe: this.formData.gruppe,
|
||||
},
|
||||
});
|
||||
},
|
||||
updateRange(rangeInterval) {
|
||||
this.$api
|
||||
.call(
|
||||
ApiLvPlan.studiensemesterDateInterval(
|
||||
rangeInterval.end.startOf("week").toISODate(),
|
||||
),
|
||||
)
|
||||
.then((res) => {
|
||||
this.studiensemester_kurzbz =
|
||||
res.data.studiensemester_kurzbz;
|
||||
this.studiensemester_start = res.data.start;
|
||||
this.studiensemester_ende = res.data.ende;
|
||||
});
|
||||
},
|
||||
getPromiseFunc(start, end) {
|
||||
return [
|
||||
this.$api.call(
|
||||
ApiLvPlan.eventsStgOrg(
|
||||
start,
|
||||
end,
|
||||
this.formData.stgkz,
|
||||
this.formData.sem,
|
||||
this.formData.verband,
|
||||
this.formData.gruppe,
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.$api.call(ApiAuthinfo.getAuthInfo()).then((res) => {
|
||||
this.uid = res.data.uid;
|
||||
this.isMitarbeiter = res.data.isMitarbeiter;
|
||||
this.isStudent = res.data.isStudent;
|
||||
});
|
||||
|
||||
this.$api
|
||||
.call(ApiLvPlan.getStudiengaenge())
|
||||
.then((result) => {
|
||||
this.listStg = result.data;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
if (this.propsViewData) {
|
||||
this.formData.stgkz = this.propsViewData.stgkz
|
||||
? this.propsViewData.stgkz
|
||||
: null;
|
||||
this.formData.sem = this.propsViewData.sem
|
||||
? this.propsViewData.sem
|
||||
: null;
|
||||
this.formData.verband = this.propsViewData.verband
|
||||
? this.propsViewData.verband
|
||||
: null;
|
||||
this.formData.gruppe = this.propsViewData.gruppe
|
||||
? this.propsViewData.gruppe
|
||||
: null;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="cis-lvplan-stg-org d-flex flex-column h-100">
|
||||
|
||||
<div class="mt-3">
|
||||
<form-form class="row row-cols-1 row-cols-md-2 row-cols-lg-4 row-cols-xl-5 g-3 mb-3">
|
||||
<form-input
|
||||
type="select"
|
||||
v-model="formData.stgkz"
|
||||
@change="loadListSem(formData.stgkz)"
|
||||
>
|
||||
<option :value="null" selected>{{ $p.t('LvPlan/chooseStg') }}</option>
|
||||
<option
|
||||
v-for="stg in listStg"
|
||||
:key="stg.studiengang_kz"
|
||||
:value="stg.studiengang_kz"
|
||||
>
|
||||
{{ stg.kurzbzlang }} ({{ stg.bezeichnung }})
|
||||
</option>
|
||||
</form-input>
|
||||
<form-input
|
||||
type="select"
|
||||
v-model="formData.sem"
|
||||
@change="loadListVerband()"
|
||||
@click="loadListSem(formData.stgkz)"
|
||||
>
|
||||
<option :value="null" selected>Semester</option>
|
||||
<option
|
||||
v-for="sem in listSem"
|
||||
:key="sem"
|
||||
:value="sem"
|
||||
>
|
||||
{{ sem }}
|
||||
</option>
|
||||
</form-input>
|
||||
<form-input
|
||||
type="select"
|
||||
v-model="formData.verband"
|
||||
@change="loadListGroup()"
|
||||
>
|
||||
<option :value="null" selected>{{ $p.t('lehre/verband') }} </option>
|
||||
<option
|
||||
v-for="verband in listVerband"
|
||||
:key="verband"
|
||||
:value="verband"
|
||||
>
|
||||
{{ verband }}
|
||||
</option>
|
||||
</form-input>
|
||||
<form-input
|
||||
type="select"
|
||||
v-model="formData.gruppe"
|
||||
>
|
||||
<option :value="null" selected>{{ $p.t('gruppenmanagement/gruppe') }}</option>
|
||||
<option
|
||||
v-for="group in listGroup"
|
||||
:key="group"
|
||||
:value="group"
|
||||
>
|
||||
{{ group }}
|
||||
</option>
|
||||
</form-input>
|
||||
<button type="button" class="btn btn-secondary" @click="loadLvPlan">{{ $p.t('LvPlan/loadLvPlan') }}</button>
|
||||
|
||||
</form-form>
|
||||
</div>
|
||||
|
||||
<fhc-calendar
|
||||
v-show="propsViewData && propsViewData.stgkz"
|
||||
ref="calendar"
|
||||
v-model:lv="formData"
|
||||
:timezone="viewData.timezone"
|
||||
:get-promise-func="getPromiseFunc"
|
||||
:date="currentDay"
|
||||
:mode="currentMode"
|
||||
@update:date="handleChangeDate"
|
||||
@update:mode="handleChangeMode"
|
||||
@update:range="updateRange"
|
||||
class="responsive-calendar"
|
||||
>
|
||||
<div
|
||||
v-if="downloadLinks"
|
||||
class="d-flex gap-1 justify-items-start"
|
||||
>
|
||||
<div v-for="{ title, icon, link } in downloadLinks">
|
||||
<a
|
||||
:href="link"
|
||||
:aria-label="title"
|
||||
class="py-1 btn btn-outline-secondary"
|
||||
>
|
||||
<div class="d-flex flex-column">
|
||||
<i aria-hidden="true" :class="icon"></i>
|
||||
<span style="font-size:.5rem">{{ title }}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</fhc-calendar>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
@@ -1,187 +0,0 @@
|
||||
import FhcCalendar from "../../Calendar/LvPlan.js";
|
||||
|
||||
import ApiLvPlan from '../.././../api/factory/lvPlan.js';
|
||||
import ApiAuthinfo from '../../../api/factory/authinfo.js';
|
||||
|
||||
export const DEFAULT_MODE_LVPLAN = 'Week';
|
||||
|
||||
export default {
|
||||
name: 'LvPlanStgOrg',
|
||||
inject: {
|
||||
cisRoot: {
|
||||
from: 'cisRoot'
|
||||
},
|
||||
},
|
||||
components: {
|
||||
FhcCalendar,
|
||||
},
|
||||
props: {
|
||||
viewData: Object,
|
||||
propsViewData: Object
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
studiensemester_kurzbz: null,
|
||||
studiensemester_start: null,
|
||||
studiensemester_ende: null,
|
||||
uid: null,
|
||||
isMitarbeiter: false,
|
||||
isStudent: false,
|
||||
listStg: [],
|
||||
currentStgBezeichnung: null
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
currentDay() {
|
||||
if (!this.propsViewData?.focus_date || isNaN(new Date(this.propsViewData?.focus_date)))
|
||||
return luxon.DateTime.now().setZone(this.viewData.timezone).toISODate();
|
||||
return this.propsViewData?.focus_date;
|
||||
},
|
||||
currentMode() {
|
||||
if (!this.propsViewData?.mode || !['day', 'week', 'month'].includes(this.propsViewData?.mode.toLowerCase()))
|
||||
return DEFAULT_MODE_LVPLAN;
|
||||
return this.propsViewData?.mode;
|
||||
},
|
||||
downloadLinks() {
|
||||
if (!this.studiensemester_start || !this.studiensemester_ende || !this.uid)
|
||||
return false;
|
||||
|
||||
let type = false;
|
||||
type = this.isStudent ? 'student' : type;
|
||||
type = this.isMitarbeiter ? 'lektor' : type;
|
||||
if (false === type)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const opts = { zone: this.viewData.timezone };
|
||||
const start = luxon.DateTime
|
||||
.fromISO(this.studiensemester_start, opts)
|
||||
.toUnixInteger();
|
||||
const ende = luxon.DateTime
|
||||
.fromISO(this.studiensemester_ende, opts)
|
||||
.toUnixInteger();
|
||||
|
||||
const download_link = FHC_JS_DATA_STORAGE_OBJECT.app_root
|
||||
+ 'cis/private/lvplan/stpl_kalender.php'
|
||||
+ '?type=' + type
|
||||
+ '&pers_uid=' + this.uid
|
||||
+ '&begin=' + start
|
||||
+ '&ende=' + ende;
|
||||
|
||||
return [
|
||||
{ title: "excel", icon: 'fa-solid fa-file-excel', link: download_link + '&format=excel' },
|
||||
{ title: "csv", icon: 'fa-solid fa-file-csv', link: download_link + '&format=csv' },
|
||||
{ title: "ical1", icon: 'fa-regular fa-calendar', link: download_link + '&format=ical&version=1&target=ical' },
|
||||
{ title: "ical2", icon: 'fa-regular fa-calendar', link: download_link + '&format=ical&version=2&target=ical' }
|
||||
];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChangeDate(day, newMode) {
|
||||
return this.handleChangeMode(newMode, day);
|
||||
},
|
||||
handleChangeMode(newMode, day) {
|
||||
const mode = newMode[0].toUpperCase() + newMode.slice(1)
|
||||
const focus_date = day.toISODate();
|
||||
|
||||
this.$router.push({
|
||||
name: "StgOrgLvPlan",
|
||||
params: {
|
||||
mode,
|
||||
focus_date,
|
||||
stgkz: this.propsViewData.stgkz,
|
||||
sem: this.propsViewData.sem,
|
||||
verband: this.propsViewData.verband,
|
||||
gruppe: this.propsViewData.gruppe,
|
||||
}
|
||||
});
|
||||
},
|
||||
updateRange(rangeInterval) {
|
||||
this.$api
|
||||
.call(ApiLvPlan.studiensemesterDateInterval(
|
||||
rangeInterval.end.startOf('week').toISODate()
|
||||
))
|
||||
.then(res => {
|
||||
this.studiensemester_kurzbz = res.data.studiensemester_kurzbz;
|
||||
this.studiensemester_start = res.data.start;
|
||||
this.studiensemester_ende = res.data.ende;
|
||||
});
|
||||
},
|
||||
getPromiseFunc(start, end) {
|
||||
return [
|
||||
this.$api.call(ApiLvPlan.eventsStgOrg(start.toISODate(), end.toISODate(), this.propsViewData.stgkz, this.propsViewData.sem, this.propsViewData.verband, this.propsViewData.gruppe)),
|
||||
//local for test
|
||||
/* this.$api.call(ApiLvPlan.eventsStgOrg(start.toISODate(), end.toISODate(), this.stgkz, this.sem, this.verband, this.gruppe))*/
|
||||
];
|
||||
},
|
||||
backToDropdown(){
|
||||
this.$router.push({
|
||||
name: "OverviewLvPlan",
|
||||
});
|
||||
}
|
||||
},
|
||||
created(){
|
||||
this.$api
|
||||
.call(ApiAuthinfo.getAuthInfo())
|
||||
.then(res => {
|
||||
this.uid = res.data.uid;
|
||||
this.isMitarbeiter = res.data.isMitarbeiter;
|
||||
this.isStudent = res.data.isStudent;
|
||||
});
|
||||
|
||||
if(this.propsViewData.stgkz) {
|
||||
this.$api
|
||||
.call(ApiLvPlan.getStudiengaenge())
|
||||
.then(result => {
|
||||
const currentStg = result.data.find(
|
||||
item => item.studiengang_kz == this.propsViewData.stgkz
|
||||
);
|
||||
this.currentStgBezeichnung = currentStg.kurzbzlang + " - " + currentStg.bezeichnung;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="cis-lvplan-stg-org d-flex flex-column h-100">
|
||||
<h2>{{ $p.t('LvPlan/headerLvPlanLvVerband') }}</h2>
|
||||
<p v-if="propsViewData.stgkz"><span><strong>{{currentStgBezeichnung}}</strong></span>
|
||||
<span v-if="propsViewData.sem" style="margin-left:10px;"> Semester: {{propsViewData.sem}} </span>
|
||||
<span v-if="propsViewData.verband" style="margin-left:10px;"> Verband: {{propsViewData.verband}} </span>
|
||||
<span v-if="propsViewData.gruppe" style="margin-left:10px;"> Gruppe: {{propsViewData.gruppe}} </span>
|
||||
<button class="py-1 btn btn-outline-secondary" :title="this.$p.t('LvPlan', 'backToDropdown')" style="margin-left:10px;"> <i class="fa fa-arrow-left fa-xs" @click="backToDropdown"></i></button>
|
||||
</p>
|
||||
<p v-else>{{ $p.t('LvPlan/noStgProvided') }}</p>
|
||||
|
||||
<fhc-calendar
|
||||
ref="calendar"
|
||||
:timezone="viewData.timezone"
|
||||
:get-promise-func="getPromiseFunc"
|
||||
:date="currentDay"
|
||||
:mode="currentMode"
|
||||
@update:date="handleChangeDate"
|
||||
@update:mode="handleChangeMode"
|
||||
@update:range="updateRange"
|
||||
class="responsive-calendar"
|
||||
>
|
||||
<div
|
||||
v-if="downloadLinks"
|
||||
class="d-flex gap-1 justify-items-start"
|
||||
>
|
||||
<div v-for="{ title, icon, link } in downloadLinks">
|
||||
<a
|
||||
:href="link"
|
||||
:aria-label="title"
|
||||
class="py-1 btn btn-outline-secondary"
|
||||
>
|
||||
<div class="d-flex flex-column">
|
||||
<i aria-hidden="true" :class="icon"></i>
|
||||
<span style="font-size:.5rem">{{ title }}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</fhc-calendar>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
@@ -30,6 +30,7 @@ export default {
|
||||
menuOpen:true,
|
||||
};
|
||||
},
|
||||
inject: ["isMobile"],
|
||||
provide(){
|
||||
return{
|
||||
setActiveEntry: this.setActiveEntry,
|
||||
@@ -58,7 +59,7 @@ export default {
|
||||
},
|
||||
site_url(){
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
fetchMenu() {
|
||||
@@ -112,10 +113,26 @@ export default {
|
||||
});
|
||||
},
|
||||
template: /*html*/`
|
||||
<button id="nav-main-btn" class="navbar-toggler rounded-0" type="button" data-bs-toggle="offcanvas" data-bs-target="#nav-main" aria-controls="nav-main" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<fhc-searchbar ref="searchbar" id="nav-search" class="fhc-searchbar w-100 py-1 py-lg-2" :searchoptions="searchbaroptions" :searchfunction="searchfunction"></fhc-searchbar>
|
||||
<div
|
||||
id="header-options-collapsible"
|
||||
class="collapse multi-collapse collapse-horizontal show"
|
||||
>
|
||||
<div class="d-flex flex-row align-items-center gap-2 h-100" style="width: 79px">
|
||||
<button id="nav-main-btn" class="navbar-toggler rounded-0 px-2 border-0" type="button" data-bs-toggle="offcanvas" data-bs-target="#nav-main" aria-controls="nav-main" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<span v-if="isMobile" class="d-flex flex-row align-items-center">
|
||||
<theme-switch></theme-switch>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<fhc-searchbar
|
||||
:searchoptions="searchbaroptions"
|
||||
:searchfunction="searchfunction"
|
||||
ref="searchbar"
|
||||
id="nav-search"
|
||||
class="fhc-searchbar w-100 py-1 py-lg-2"
|
||||
></fhc-searchbar>
|
||||
<div id="nav-logo" class="d-none d-lg-block">
|
||||
<div class="d-flex h-100 justify-content-between">
|
||||
<a :href="rootUrl">
|
||||
@@ -124,22 +141,32 @@ export default {
|
||||
<theme-switch></theme-switch>
|
||||
</div>
|
||||
</div>
|
||||
<div id="nav-user">
|
||||
<button id="nav-user-btn" class="btn btn-link rounded-0" type="button" data-bs-toggle="collapse" data-bs-target="#nav-user-menu" aria-expanded="false" aria-controls="nav-user-menu">
|
||||
<img :src="avatarUrl" :alt="$p.t('profilUpdate/profilBild')" class="bg-dark avatar rounded-circle border border-dark"/>
|
||||
</button>
|
||||
<ul ref="navUserDropdown"
|
||||
@[\`shown.bs.collapse\`]="handleShowNavUser"
|
||||
@[\`hide.bs.collapse\`]="handleHideNavUser"
|
||||
id="nav-user-menu" class="top-100 end-0 collapse list-unstyled" aria-labelledby="nav-user-btn">
|
||||
<li><a class="fhc-dark-bg btn rounded-0 d-block" :href="site_url + '/Cis/Profil'" id="menu-profil">Profil</a></li>
|
||||
<li >
|
||||
<cis-sprachen @languageChanged="fetchMenu"></cis-sprachen>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider m-0 "></li>
|
||||
<li ><a class="fhc-dark-bg btn rounded-0 d-block" :href="logoutUrl">Logout</a></li>
|
||||
</ul>
|
||||
|
||||
<div
|
||||
id="header-usermenu-collapsible"
|
||||
class="collapse multi-collapse collapse-horizontal show"
|
||||
>
|
||||
<div
|
||||
:style="!isMobile ? '' : 'width: 51px'"
|
||||
id="nav-user"
|
||||
>
|
||||
<button id="nav-user-btn" class="btn btn-link rounded-0" type="button" data-bs-toggle="collapse" data-bs-target="#nav-user-menu" aria-expanded="false" aria-controls="nav-user-menu">
|
||||
<img :src="avatarUrl" :alt="$p.t('profilUpdate/profilBild')" class="bg-dark avatar rounded-circle border border-dark"/>
|
||||
</button>
|
||||
<ul ref="navUserDropdown"
|
||||
@[\`shown.bs.collapse\`]="handleShowNavUser"
|
||||
@[\`hide.bs.collapse\`]="handleHideNavUser"
|
||||
id="nav-user-menu" class="top-100 end-0 collapse list-unstyled" aria-labelledby="nav-user-btn">
|
||||
<li><a class="fhc-dark-bg btn rounded-0 d-block" :href="site_url + '/Cis/Profil'" id="menu-profil">Profil</a></li>
|
||||
<li >
|
||||
<cis-sprachen @languageChanged="fetchMenu"></cis-sprachen>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider m-0 "></li>
|
||||
<li ><a class="fhc-dark-bg btn rounded-0 d-block" :href="logoutUrl">Logout</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav id="nav-main" class="offcanvas offcanvas-start" tabindex="-1" aria-labelledby="nav-main-btn" data-bs-backdrop="false">
|
||||
<div id="nav-main-sticky">
|
||||
<div id="nav-main-toggle" class="position-static d-none d-lg-block ">
|
||||
|
||||
@@ -2,8 +2,7 @@ import FhcCalendar from "../../Calendar/LvPlan.js";
|
||||
|
||||
import ApiLvPlan from '../../../api/factory/lvPlan.js';
|
||||
|
||||
export const DEFAULT_MODE_RAUMINFO_MOBILE = 'List';
|
||||
export const DEFAULT_MODE_RAUMINFO_DESKTOP = 'Week';
|
||||
export const DEFAULT_MODE_RAUMINFO = 'Week'
|
||||
|
||||
export default {
|
||||
name: "RoomInformation",
|
||||
@@ -14,14 +13,12 @@ export default {
|
||||
viewData: Object, // NOTE(chris): this is inherited from router-view
|
||||
propsViewData: Object
|
||||
},
|
||||
inject: ["isMobile"],
|
||||
computed: {
|
||||
currentDay() {
|
||||
return this.propsViewData?.focus_date || luxon.DateTime.now().setZone(this.viewData.timezone).toISODate();
|
||||
},
|
||||
currentMode() {
|
||||
const defaultMode = this.isMobile ? DEFAULT_MODE_RAUMINFO_MOBILE : DEFAULT_MODE_RAUMINFO_DESKTOP;
|
||||
return this.propsViewData?.mode || defaultMode;
|
||||
return this.propsViewData?.mode || DEFAULT_MODE_RAUMINFO;
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
|
||||
@@ -9,7 +9,6 @@ import QuickLinks from "./ProfilComponents/QuickLinks.js";
|
||||
import ProfilEmails from "./ProfilComponents/ProfilEmails.js";
|
||||
import RoleInformation from "./ProfilComponents/RoleInformation.js";
|
||||
import ProfilInformation from "./ProfilComponents/ProfilInformation.js";
|
||||
import CalendarSync from "./ProfilComponents/CalendarSync.js";
|
||||
|
||||
import ApiProfilUpdate from '../../../api/factory/profilUpdate.js';
|
||||
import { dateFilter } from '../../../tabulator/filters/Dates.js';
|
||||
@@ -27,7 +26,6 @@ export default {
|
||||
ProfilEmails,
|
||||
RoleInformation,
|
||||
ProfilInformation,
|
||||
CalendarSync,
|
||||
},
|
||||
|
||||
inject: ["sortProfilUpdates", "collapseFunction", "language","isEditable"],
|
||||
@@ -105,7 +103,7 @@ export default {
|
||||
},
|
||||
],
|
||||
},
|
||||
quickLinks: [],
|
||||
|
||||
betriebsmittel_table_options: {
|
||||
persistenceID: "filterTableMaProfilBetriebsmittel",
|
||||
persistence: {
|
||||
@@ -162,7 +160,6 @@ export default {
|
||||
props: {
|
||||
data: Object,
|
||||
editData: Object,
|
||||
calendarSyncUrls: Array,
|
||||
},
|
||||
|
||||
methods: {
|
||||
@@ -316,6 +313,7 @@ export default {
|
||||
});
|
||||
//? sorts the profil Updates: pending -> accepted -> rejected
|
||||
this.data.profilUpdates?.sort(this.sortProfilUpdates);
|
||||
|
||||
},
|
||||
watch: {
|
||||
'data.funktionen'(newVal) {
|
||||
@@ -333,6 +331,12 @@ export default {
|
||||
<edit-profil v-if="showModal" ref="editModal" :isMitarbeiter="true" @hideBsModal="hideEditProfilModal" :value="JSON.parse(JSON.stringify(filteredEditData))" :titel="$p.t('profil','profilBearbeiten')"></edit-profil>
|
||||
<div class="row">
|
||||
<div class="d-md-none col-12 ">
|
||||
<!--TODO: uncomment when implemented
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<quick-links :title="$p.t('profil','quickLinks')" :mobile="true"></quick-links>
|
||||
</div>
|
||||
</div>-->
|
||||
<!-- Bearbeiten Button -->
|
||||
<div v-if="isEditable" class="row mb-3 ">
|
||||
<div class="col">
|
||||
@@ -461,11 +465,17 @@ export default {
|
||||
</div>
|
||||
<!-- START OF SIDE PANEL -->
|
||||
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
|
||||
<div v-if="quickLinks.length" class="row mb-4">
|
||||
<div class="col">
|
||||
<quick-links :title="$p.t('profil/quickLinks')" :links="quickLinks" />
|
||||
</div>
|
||||
</div>
|
||||
<!--TODO: uncomment when implemented
|
||||
<div class="row d-none d-md-block mb-3">
|
||||
|
||||
<div class="col">
|
||||
|
||||
<quick-links :title="$p.t('profil','quickLinks')"></quick-links>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>-->
|
||||
<!-- Bearbeiten Button -->
|
||||
<div class="row d-none d-md-block ">
|
||||
<div class="col mb-3">
|
||||
@@ -491,17 +501,12 @@ export default {
|
||||
<ausweis-status :data="data.zutrittsdatum"></ausweis-status>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<!-- MAILVERTEILER -->
|
||||
<mailverteiler :data="data?.mailverteiler" :title="$p.t('profil','mailverteiler')"></mailverteiler>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<calendar-sync :uid="$props.data.username" :calendarSyncUrls="$props.calendarSyncUrls"></calendar-sync>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import {CoreFilterCmpt} from "../../../components/filter/Filter.js";
|
||||
import Mailverteiler from "./ProfilComponents/Mailverteiler.js";
|
||||
import QuickLinks from "./ProfilComponents/QuickLinks.js";
|
||||
import RoleInformation from "./ProfilComponents/RoleInformation.js";
|
||||
import ProfilEmails from "./ProfilComponents/ProfilEmails.js";
|
||||
import ProfilInformation from "./ProfilComponents/ProfilInformation.js";
|
||||
import QuickLinks from "./ProfilComponents/QuickLinks.js";
|
||||
|
||||
import { dateFilter } from '../../../tabulator/filters/Dates.js';
|
||||
|
||||
@@ -11,10 +11,10 @@ export default {
|
||||
components: {
|
||||
CoreFilterCmpt,
|
||||
Mailverteiler,
|
||||
QuickLinks,
|
||||
RoleInformation,
|
||||
ProfilEmails,
|
||||
ProfilInformation,
|
||||
QuickLinks,
|
||||
},
|
||||
inject: ["collapseFunction", "language"],
|
||||
data() {
|
||||
@@ -90,12 +90,11 @@ export default {
|
||||
},
|
||||
],
|
||||
},
|
||||
quickLinks: [],
|
||||
};
|
||||
},
|
||||
|
||||
//? this is the prop passed to the dynamic component with the custom data of the view
|
||||
props: ["data", "permissions"],
|
||||
props: ["data"],
|
||||
methods: {
|
||||
funktionenTableBuilt: function () {
|
||||
this.$refs.funktionenTable.tabulator.setData(this.data.funktionen);
|
||||
@@ -190,21 +189,6 @@ export default {
|
||||
this.preloadedPhrasen.wochenstundenPhrase = this.$p.t('profil/wochenstunden');
|
||||
this.preloadedPhrasen.loaded = true;
|
||||
});
|
||||
|
||||
if (this.$props.permissions["basis/other_lv_plan"]) {
|
||||
this.quickLinks.push(
|
||||
{
|
||||
icon: "fa-calendar-days",
|
||||
phrase: "lehre/stundenplan",
|
||||
action: () => {
|
||||
this.$router.push({
|
||||
name: "OtherLvPlan",
|
||||
params: { otherUid: this.$props.data.username },
|
||||
})
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
template: /*html*/ `
|
||||
@@ -258,7 +242,7 @@ export default {
|
||||
</div>
|
||||
<!-- START OF THE SECOND PROFIL INFORMATION ROW -->
|
||||
<!-- ROW WITH PROFIL IMAGE AND INFORMATION END -->
|
||||
</div>
|
||||
</div >
|
||||
<!-- SECOND ROW UNDER THE PROFIL IMAGE AND INFORMATION WITH THE TABLES -->
|
||||
<div class="row">
|
||||
<!-- FIRST TABLE -->
|
||||
@@ -272,22 +256,26 @@ export default {
|
||||
<!-- START OF SIDE PANEL -->
|
||||
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
|
||||
<!-- VISIBLE UNTIL VIEWPORT MD -->
|
||||
<div v-if="quickLinks.length" class="row mb-4">
|
||||
<div class="col">
|
||||
<quick-links :title="$p.t('profil/quickLinks')" :links="quickLinks" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<!-- MAILVERTEILER -->
|
||||
<mailverteiler :data="data?.mailverteiler" :title="$p.t('profil','mailverteiler')"></mailverteiler>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF SIDE PANEL -->
|
||||
</div>
|
||||
<!--TODO: uncomment when implemented
|
||||
<div class="row d-none d-md-block mb-3">
|
||||
<div class="col">
|
||||
|
||||
<quick-links :title="$p.t('profil','quickLinks')" ></quick-links>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<!-- MAILVERTEILER -->
|
||||
<mailverteiler :data="data?.mailverteiler" :title="$p.t('profil','mailverteiler')"></mailverteiler>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF SIDE PANEL -->
|
||||
</div>
|
||||
<!-- END OF CONTAINER ROW-->
|
||||
</div>
|
||||
<!-- END OF CONTAINER -->
|
||||
</div>
|
||||
<!-- END OF CONTAINER -->
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
|
||||
@@ -4,8 +4,8 @@ import ViewStudentProfil from "./StudentViewProfil.js";
|
||||
import ViewMitarbeiterProfil from "./MitarbeiterViewProfil.js";
|
||||
import Loading from "../../Loader.js";
|
||||
|
||||
import ApiProfil from "../../../api/factory/profil.js";
|
||||
import ApiProfilUpdate from "../../../api/factory/profilUpdate.js";
|
||||
import ApiProfil from '../../../api/factory/profil.js';
|
||||
import ApiProfilUpdate from '../../../api/factory/profilUpdate.js';
|
||||
|
||||
Vue.$collapseFormatter = function (data) {
|
||||
//data - an array of objects containing the column title and value for each cell
|
||||
@@ -35,7 +35,7 @@ Vue.$collapseFormatter = function (data) {
|
||||
};
|
||||
|
||||
export const Profil = {
|
||||
name: "Profil",
|
||||
name: 'Profil',
|
||||
components: {
|
||||
StudentProfil,
|
||||
MitarbeiterProfil,
|
||||
@@ -46,11 +46,11 @@ export const Profil = {
|
||||
props: {
|
||||
uid: {
|
||||
type: String,
|
||||
required: false,
|
||||
required:false,
|
||||
},
|
||||
viewData: {
|
||||
type: Object,
|
||||
},
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -67,12 +67,12 @@ export const Profil = {
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
isEditable: Vue.computed(() => this.isEditable),
|
||||
isEditable: Vue.computed(()=>this.isEditable),
|
||||
profilUpdateStates: Vue.computed(() =>
|
||||
this.profilUpdateStates ? this.profilUpdateStates : false,
|
||||
this.profilUpdateStates ? this.profilUpdateStates : false
|
||||
),
|
||||
profilUpdateTopic: Vue.computed(() =>
|
||||
this.profilUpdateTopic ? this.profilUpdateTopic : false,
|
||||
this.profilUpdateTopic ? this.profilUpdateTopic : false
|
||||
),
|
||||
setLoading: (newValue) => {
|
||||
this.loading = newValue;
|
||||
@@ -130,12 +130,8 @@ export const Profil = {
|
||||
//? if they have the same status the insert date is used for ordering
|
||||
if (ele1.status === ele2.status) {
|
||||
result =
|
||||
new Date(
|
||||
ele2.insertamum.split(".").reverse().join("-"),
|
||||
) -
|
||||
new Date(
|
||||
ele1.insertamum.split(".").reverse().join("-"),
|
||||
);
|
||||
new Date(ele2.insertamum.split(".").reverse().join("-")) -
|
||||
new Date(ele1.insertamum.split(".").reverse().join("-"));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
@@ -161,11 +157,11 @@ export const Profil = {
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
|
||||
|
||||
this.$api
|
||||
.call(ApiProfil.profilViewData(this.$route.params.uid ?? null))
|
||||
.then((response) => response.data)
|
||||
.then((data) => {
|
||||
.call(ApiProfil.profilViewData(this.$route.params.uid??null))
|
||||
.then((response) => response.data).then(data=>{
|
||||
this.view = data?.profil_data.view;
|
||||
this.data = data?.profil_data.data;
|
||||
this.isEditable = data?.editable ?? false;
|
||||
@@ -173,6 +169,8 @@ export const Profil = {
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
zustellAdressenCount() {
|
||||
if (!this.data || !this.data.adressen) {
|
||||
@@ -188,7 +186,7 @@ export const Profil = {
|
||||
})
|
||||
.map((adresse) => {
|
||||
return adresse.requested_change.adresse_id;
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -199,9 +197,8 @@ export const Profil = {
|
||||
.every((adresse) =>
|
||||
this.data.profilUpdates.some(
|
||||
(update) =>
|
||||
update.requested_change.adresse_id ==
|
||||
adresse.adresse_id,
|
||||
),
|
||||
update.requested_change.adresse_id == adresse.adresse_id
|
||||
)
|
||||
)
|
||||
) {
|
||||
adressenArray = adressenArray.concat(
|
||||
@@ -211,11 +208,12 @@ export const Profil = {
|
||||
})
|
||||
.map((adr) => {
|
||||
return adr.adresse_id;
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return [...new Set(adressenArray)];
|
||||
|
||||
},
|
||||
zustellKontakteCount() {
|
||||
if (!this.data || !this.data.kontakte) {
|
||||
@@ -228,17 +226,14 @@ export const Profil = {
|
||||
kontakteArray = kontakteArray.concat(
|
||||
this.data.profilUpdates
|
||||
.filter((update) => {
|
||||
return (
|
||||
update.status === "Pending" &&
|
||||
update.requested_change.zustellung
|
||||
);
|
||||
return update.status === 'Pending' && update.requested_change.zustellung;
|
||||
})
|
||||
.map((kontant) => {
|
||||
return {
|
||||
kontakt_id: kontant.requested_change.kontakt_id,
|
||||
kontakttyp: kontant.requested_change.kontakttyp,
|
||||
};
|
||||
}),
|
||||
kontakt_id: kontant.requested_change.kontakt_id,
|
||||
kontakttyp: kontant.requested_change.kontakttyp
|
||||
};
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -249,10 +244,8 @@ export const Profil = {
|
||||
.every((kontakt) =>
|
||||
this.data.profilUpdates.some(
|
||||
(update) =>
|
||||
update.status === "Pending" &&
|
||||
update.requested_change.kontakt_id ==
|
||||
kontakt.kontakt_id,
|
||||
),
|
||||
update.status === 'Pending' && update.requested_change.kontakt_id == kontakt.kontakt_id
|
||||
)
|
||||
)
|
||||
) {
|
||||
kontakteArray = kontakteArray.concat(
|
||||
@@ -262,10 +255,10 @@ export const Profil = {
|
||||
})
|
||||
.map((kon) => {
|
||||
return {
|
||||
kontakt_id: kon.kontakt_id,
|
||||
kontakttyp: kon.kontakttyp,
|
||||
};
|
||||
}),
|
||||
kontakt_id: kon.kontakt_id,
|
||||
kontakttyp: kon.kontakttyp
|
||||
};
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -273,6 +266,7 @@ export const Profil = {
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
|
||||
filteredEditData() {
|
||||
if (!this.data) {
|
||||
return;
|
||||
@@ -336,12 +330,8 @@ export const Profil = {
|
||||
// excludes all contacts that are already used in pending profil update requests
|
||||
return !this.data.profilUpdates?.some(
|
||||
(update) =>
|
||||
update.status ===
|
||||
this.profilUpdateStates[
|
||||
"Pending"
|
||||
] &&
|
||||
update.requested_change?.kontakt_id ===
|
||||
item.kontakt_id,
|
||||
update.status === this.profilUpdateStates["Pending"] &&
|
||||
update.requested_change?.kontakt_id === item.kontakt_id
|
||||
);
|
||||
})
|
||||
.map((kontakt) => {
|
||||
@@ -357,18 +347,12 @@ export const Profil = {
|
||||
topic: this.profilUpdateTopic?.["Private Adressen"],
|
||||
data: this.data.adressen
|
||||
?.filter((item) => {
|
||||
return !this.data.profilUpdates?.some(
|
||||
(update) => {
|
||||
return (
|
||||
update.status ===
|
||||
this.profilUpdateStates[
|
||||
"Pending"
|
||||
] &&
|
||||
update.requested_change
|
||||
?.adresse_id == item.adresse_id
|
||||
);
|
||||
},
|
||||
);
|
||||
return !this.data.profilUpdates?.some((update) => {
|
||||
return (
|
||||
update.status === this.profilUpdateStates["Pending"] &&
|
||||
update.requested_change?.adresse_id == item.adresse_id
|
||||
);
|
||||
});
|
||||
})
|
||||
.map((adresse) => {
|
||||
return {
|
||||
@@ -390,12 +374,12 @@ export const Profil = {
|
||||
this.$refs.loadingModalRef.hide();
|
||||
}
|
||||
},
|
||||
uid(newVal, oldVal) {
|
||||
this.load();
|
||||
},
|
||||
uid (newVal, oldVal) {
|
||||
this.load()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.load();
|
||||
this.load()
|
||||
},
|
||||
template: `
|
||||
<div>
|
||||
@@ -404,14 +388,9 @@ export const Profil = {
|
||||
</div>
|
||||
<div v-else>
|
||||
<loading ref="loadingModalRef" :timeout="0"></loading>
|
||||
<component
|
||||
:is="view"
|
||||
:data="data"
|
||||
:editData="filteredEditData"
|
||||
:permissions="$props.viewData.permissions"
|
||||
:calendarSyncUrls="$props.viewData.calendarSyncUrls"></component>
|
||||
<component :is="view" :data="data" :editData="filteredEditData" ></component>
|
||||
</div>
|
||||
</div>`,
|
||||
};
|
||||
}
|
||||
|
||||
export default Profil;
|
||||
export default Profil
|
||||
@@ -1,54 +0,0 @@
|
||||
export default {
|
||||
name: "CalendarSync",
|
||||
props: { uid: String, calendarSyncUrls: Array },
|
||||
data() {
|
||||
return {
|
||||
syncInstructionsUrlWithoutParam:
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
"cms/content.php?content_id=",
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
copyUrlToClipboard(url) {
|
||||
navigator.clipboard.writeText(url);
|
||||
this.$fhcAlert.alertSuccess(
|
||||
this.$p.t("profil/calendar_sync_clipboard_copy_confirmation"),
|
||||
);
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
{{ $p.t("profil/calendar_sync") }}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-column gap-3">
|
||||
<a
|
||||
target="_blank"
|
||||
:href="syncInstructionsUrlWithoutParam + $p.t('DMS-Link/lvplanSyncFAQ')"
|
||||
class="fhc-link-color d-flex flex-row gap-2 align-items-center"
|
||||
>
|
||||
<span>
|
||||
<i class="fa-solid fa-up-right-from-square ms-2"></i>
|
||||
</span>
|
||||
<span>
|
||||
{{ $p.t("profil/calendar_sync_instructions") }}
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
v-for="syncUrl in $props.calendarSyncUrls"
|
||||
:key="syncUrl.identifier"
|
||||
@click.prevent="copyUrlToClipboard(syncUrl.url)"
|
||||
@contextmenu.prevent="copyUrlToClipboard(syncUrl.url)"
|
||||
href="#"
|
||||
class="fhc-link-color d-flex flex-row gap-2 align-items-center"
|
||||
>
|
||||
<span>
|
||||
<i class="fa-regular fa-copy ms-2 text-decoration-none"></i>
|
||||
</span>
|
||||
{{ $p.t(syncUrl.labelPhrase) }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>`,
|
||||
};
|
||||
@@ -1,31 +1,53 @@
|
||||
export default {
|
||||
name: "QuickLinks",
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
links: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
template: `
|
||||
//TODO: To be implemented
|
||||
props: {
|
||||
data: {
|
||||
type: String,
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
mobile: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hideCollapse: function () {
|
||||
this.collapseOpen = false;
|
||||
},
|
||||
showCollapse: function () {
|
||||
this.collapseOpen = true;
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
collapseOpen: false,
|
||||
};
|
||||
},
|
||||
template: /*html*/ `
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
{{title}}
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-row align-items-center gap-3 flex-wrap">
|
||||
<div v-for="link in links" @click="link.action()" type="button" class="d-flex flex-row gap-2 px-3 py-2 border fhc-primary">
|
||||
<div><i class="fa" :class="link.icon"></i></div>
|
||||
{{ $p.t(link.phrase) }}
|
||||
<div><i class="fa fa-arrow-up-right-from-square" style="color:var(--fhc-light) !important"></i></div>
|
||||
<template v-if="mobile">
|
||||
<button class="btn btn-outline-primary" data-bs-toggle="collapse" data-bs-target="#quickLinks" :aria-expanded="collapseOpen" aria-controls="quickLinks" >
|
||||
{{title}}
|
||||
<i class="fa " :class="collapseOpen?'fa-chevron-up':'fa-chevron-down'"></i>
|
||||
</button>
|
||||
<div @[\`show.bs.collapse\`]="collapseOpen=true;" @[\`hide.bs.collapse\`]="collapseOpen=false;" class="mt-1 collapse" id="quickLinks">
|
||||
<div class="list-group">
|
||||
<a href="#" class="list-group-item list-group-item-action">{{$p.t('profil','zeitwuensche')}}</a>
|
||||
<a href="#" class="list-group-item list-group-item-action">{{$p.t('profil','lehrveranstaltungen')}}</a>
|
||||
<a href="#" class="list-group-item list-group-item-action ">{{$p.t('profil','zeitsperren')}}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="card-header">{{title}}</div>
|
||||
<div class="card-body">
|
||||
<a style="text-decoration:none" class="my-1 d-block" href="#">{{$p.t('profil','zeitwuensche')}}</a>
|
||||
<a style="text-decoration:none" class="my-1 d-block" href="#">{{$p.t('profil','lehrveranstaltungen')}}</a>
|
||||
<a style="text-decoration:none" class="my-1 d-block" href="#">{{$p.t('profil','zeitsperren')}}</a>
|
||||
</div>
|
||||
</template>
|
||||
</div>`,
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {CoreFilterCmpt} from "../../../components/filter/Filter.js";
|
||||
import Mailverteiler from "./ProfilComponents/Mailverteiler.js";
|
||||
import AusweisStatus from "./ProfilComponents/FhAusweisStatus.js";
|
||||
import QuickLinks from "./ProfilComponents/QuickLinks.js";
|
||||
import Adresse from "./ProfilComponents/Adresse.js";
|
||||
import Kontakt from "./ProfilComponents/Kontakt.js";
|
||||
import ProfilEmails from "./ProfilComponents/ProfilEmails.js";
|
||||
@@ -8,8 +9,6 @@ import RoleInformation from "./ProfilComponents/RoleInformation.js";
|
||||
import ProfilInformation from "./ProfilComponents/ProfilInformation.js";
|
||||
import FetchProfilUpdates from "./ProfilComponents/FetchProfilUpdates.js";
|
||||
import EditProfil from "./ProfilModal/EditProfil.js";
|
||||
import QuickLinks from "./ProfilComponents/QuickLinks.js";
|
||||
import CalendarSync from "./ProfilComponents/CalendarSync.js";
|
||||
|
||||
import ApiProfilUpdate from '../../../api/factory/profilUpdate.js';
|
||||
import { dateFilter } from '../../../tabulator/filters/Dates.js';
|
||||
@@ -19,6 +18,7 @@ export default {
|
||||
CoreFilterCmpt,
|
||||
Mailverteiler,
|
||||
AusweisStatus,
|
||||
QuickLinks,
|
||||
Adresse,
|
||||
Kontakt,
|
||||
ProfilEmails,
|
||||
@@ -26,8 +26,6 @@ export default {
|
||||
ProfilInformation,
|
||||
FetchProfilUpdates,
|
||||
EditProfil,
|
||||
QuickLinks,
|
||||
CalendarSync,
|
||||
},
|
||||
inject: ["sortProfilUpdates", "collapseFunction", "language","isEditable"],
|
||||
data() {
|
||||
@@ -97,14 +95,12 @@ export default {
|
||||
},
|
||||
],
|
||||
},
|
||||
quickLinks: [],
|
||||
};
|
||||
},
|
||||
|
||||
props: {
|
||||
data: Object,
|
||||
editData: Object,
|
||||
calendarSyncUrls: Array,
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
@@ -269,7 +265,15 @@ export default {
|
||||
:value="JSON.parse(JSON.stringify(filteredEditData))" :titel="$p.t('profil','profilBearbeiten')"></edit-profil>
|
||||
<!-- ROW -->
|
||||
<div class="row">
|
||||
<!-- HIDDEN QUICK LINKS -->
|
||||
<div class="d-md-none col-12 ">
|
||||
<!--TODO: uncomment when implemented
|
||||
<div class="row py-2">
|
||||
<div class="col">
|
||||
<quick-links :title="$p.t('profil','quickLinks')" :mobile="true"></quick-links>
|
||||
</div>
|
||||
</div>-->
|
||||
|
||||
<!-- Bearbeiten Button -->
|
||||
<div v-if="isEditable" class="row ">
|
||||
<div class="col mb-3">
|
||||
@@ -399,11 +403,12 @@ export default {
|
||||
</div>
|
||||
<!-- START OF SIDE PANEL -->
|
||||
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
|
||||
<div v-if="quickLinks.length" class="row mb-4">
|
||||
<!--TODO: uncomment when implemented
|
||||
<div class="row d-none d-md-block mb-3">
|
||||
<div class="col">
|
||||
<quick-links :title="$p.t('profil/quickLinks')" :links="quickLinks" />
|
||||
<quick-links :title="$p.t('profil','quickLinks')"></quick-links>
|
||||
</div>
|
||||
</div>
|
||||
</div>-->
|
||||
<!-- Bearbeiten Button -->
|
||||
<div class="row d-none d-md-block">
|
||||
<div class="col mb-3">
|
||||
@@ -429,18 +434,13 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
<!-- START OF THE SECOND ROW IN THE SIDE PANEL -->
|
||||
<div class="row mb-3">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<!-- HIER SIND DIE MAILVERTEILER -->
|
||||
<mailverteiler :title="$p.t('profil','mailverteiler')" :data="data?.mailverteiler"></mailverteiler>
|
||||
</div>
|
||||
<!-- END OF THE SECOND ROW IN THE SIDE PANEL -->
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<calendar-sync :uid="$props.data.username" :calendarSyncUrls="$props.calendarSyncUrls"></calendar-sync>
|
||||
</div>
|
||||
</div>
|
||||
<!-- END OF SIDE PANEL -->
|
||||
</div>
|
||||
<!-- END OF CONTAINER ROW-->
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
import QuickLinks from "./ProfilComponents/QuickLinks.js";
|
||||
import Mailverteiler from "./ProfilComponents/Mailverteiler.js";
|
||||
import ProfilEmails from "./ProfilComponents/ProfilEmails.js";
|
||||
import RoleInformation from "./ProfilComponents/RoleInformation.js";
|
||||
import ProfilInformation from "./ProfilComponents/ProfilInformation.js";
|
||||
import QuickLinks from "./ProfilComponents/QuickLinks.js";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
components: {
|
||||
QuickLinks,
|
||||
Mailverteiler,
|
||||
ProfilEmails,
|
||||
RoleInformation,
|
||||
ProfilInformation,
|
||||
QuickLinks,
|
||||
},
|
||||
props: ["data", "permissions"],
|
||||
data() {
|
||||
return {
|
||||
quickLinks: [],
|
||||
};
|
||||
},
|
||||
|
||||
props: ["data"],
|
||||
provide() {
|
||||
return {
|
||||
studiengang_kz: Vue.computed({ get: () => this.data.studiengang_kz }),
|
||||
}
|
||||
},
|
||||
|
||||
methods: {},
|
||||
|
||||
computed: {
|
||||
fotoStatus() {
|
||||
return this.data?.fotoStatus ?? null;
|
||||
@@ -86,28 +88,23 @@ export default {
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {},
|
||||
created() {
|
||||
if (this.$props.permissions["basis/other_lv_plan"]) {
|
||||
this.quickLinks.push(
|
||||
{
|
||||
icon: "fa-calendar-days",
|
||||
phrase: "lehre/stundenplan",
|
||||
action: () => {
|
||||
this.$router.push({
|
||||
name: "OtherLvPlan",
|
||||
params: { otherUid: this.$props.data.username },
|
||||
})
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
mounted() {
|
||||
},
|
||||
|
||||
template: /*html*/ `
|
||||
|
||||
<div class="container-fluid text-break fhc-form" >
|
||||
<!-- ROW -->
|
||||
<div class="row">
|
||||
<!-- HIDDEN QUICK LINKS -->
|
||||
<!-- uncomment when implemented
|
||||
<div class="d-md-none col-12 ">
|
||||
|
||||
<quick-links :title="$p.t('profil','quickLinks')" :mobile="true"></quick-links>
|
||||
|
||||
</div>-->
|
||||
<!-- END OF HIDDEN QUCK LINKS -->
|
||||
<!-- MAIN PANNEL -->
|
||||
<div class="col-sm-12 col-md-8 col-xxl-9 ">
|
||||
<!-- ROW WITH PROFIL IMAGE AND INFORMATION -->
|
||||
@@ -115,18 +112,12 @@ export default {
|
||||
<!-- ROW WITH THE PROFIL INFORMATION -->
|
||||
<div class="row mb-4">
|
||||
<!-- FIRST KAESTCHEN -->
|
||||
<div class="col-lg-12 col-xl-6 ">
|
||||
<div class="col-lg-12 col-xl-6 ">
|
||||
<div class="row mb-4">
|
||||
<div class="col">
|
||||
<profil-information :data="profilInformation" :title="$p.t('profil','studentIn')" :fotoStatus="fotoStatus"></profil-information>
|
||||
</div>
|
||||
</div>
|
||||
<!-- SECOND ROW OF FIRST COLUMN -->
|
||||
<div class="row mb-4">
|
||||
<div class="col">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- START OF SECOND PROFIL INFORMATION COLUMN -->
|
||||
<!-- END OF PROFIL INFORMATION ROW -->
|
||||
<!-- INFORMATION CONTENT END -->
|
||||
@@ -154,12 +145,17 @@ export default {
|
||||
</div>
|
||||
<!-- START OF SIDE PANEL -->
|
||||
<div class="col-md-4 col-xxl-3 col-sm-12 text-break" >
|
||||
<!-- START OF THE FIRST ROW IN THE SIDE PANEL -->
|
||||
<div v-if="quickLinks.length" class="row mb-4">
|
||||
<div class="col">
|
||||
<quick-links :title="$p.t('profil/quickLinks')" :links="quickLinks" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- SRART OF QUICK LINKS IN THE SIDE PANEL -->
|
||||
<!-- START OF THE FIRDT ROW IN THE SIDE PANEL -->
|
||||
<!-- THESE QUCK LINKS ARE ONLY VISIBLE UNTIL VIEWPORT MD -->
|
||||
<!--TODO: uncomment when implemented
|
||||
<div class="row d-none d-md-block mb-3">
|
||||
<div class="col">
|
||||
|
||||
<quick-links :title="$p.t('profil','quickLinks')"></quick-links>
|
||||
|
||||
</div>
|
||||
</div>-->
|
||||
<!-- START OF THE SECOND ROW IN THE SIDE PANEL -->
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
|
||||
@@ -31,7 +31,7 @@ export default {
|
||||
this.event.lektor.slice(0, 3).map(lektor => lektor.kurzbz).join("\n")
|
||||
+ "\n" + this.$p.t('lehre/weitereLektoren', [this.event.lektor.length - 3])
|
||||
].join(": "));
|
||||
} else {
|
||||
} else {;
|
||||
tooltipArray.push([
|
||||
this.$p.t('lehre/lektor'),
|
||||
this.event.lektor.map(lektor => lektor.kurzbz).join("\n")
|
||||
|
||||
@@ -142,6 +142,7 @@ export default {
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<lv-menu v-if="lvMenu.length && $route.name === 'MyLvPlan'" :containerStyles="['p-0']" :rowStyles="['m-0']" :menu="lvMenu" />
|
||||
|
||||
<lv-menu :containerStyles="['p-0']" :rowStyles="['m-0']" v-if="lvMenu.length" :menu="lvMenu" />
|
||||
</div>`,
|
||||
}
|
||||
@@ -21,69 +21,71 @@ export default {
|
||||
dms,
|
||||
cms,
|
||||
mergedStudent,
|
||||
mergedPerson
|
||||
mergedPerson,
|
||||
},
|
||||
props: {
|
||||
searchoptions: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
searchfunction: {
|
||||
type: Function,
|
||||
required: true
|
||||
},
|
||||
showBtnSubmit: Boolean
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
query: Vue.computed(() => this.lastQuery)
|
||||
};
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
searchtimer: null,
|
||||
hidetimer: null,
|
||||
searchsettings: {
|
||||
searchstr: this.getSearchStr(),
|
||||
types: this.getInitiallySelectedTypes(),
|
||||
},
|
||||
searchresult: [],
|
||||
searchmode: '',
|
||||
showresult: false,
|
||||
searching: false,
|
||||
error: null,
|
||||
abortController: null,
|
||||
props: {
|
||||
searchoptions: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
searchfunction: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
showBtnSubmit: Boolean,
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
query: Vue.computed(() => this.lastQuery),
|
||||
};
|
||||
},
|
||||
inject: ["isMobile"],
|
||||
data: function () {
|
||||
return {
|
||||
searchtimer: null,
|
||||
hidetimer: null,
|
||||
searchsettings: {
|
||||
searchstr: this.getSearchStr(),
|
||||
types: this.getInitiallySelectedTypes(),
|
||||
},
|
||||
searchresult: [],
|
||||
searchmode: "",
|
||||
showresult: false,
|
||||
searching: false,
|
||||
error: null,
|
||||
abortController: null,
|
||||
settingsDropdown: null,
|
||||
lastQuery: ''
|
||||
};
|
||||
},
|
||||
lastQuery: "",
|
||||
isSearchShownInMobileView: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
searchTypesPlaceholder() {
|
||||
if (!this.searchsettings.types.length) {
|
||||
return Object.values(this.typeLabels).join(' / ');
|
||||
return Object.values(this.typeLabels).join(" / ");
|
||||
}
|
||||
return this.searchsettings.types.map(type => this.typeLabels[type]).join(' / ');
|
||||
return this.searchsettings.types
|
||||
.map((type) => this.typeLabels[type])
|
||||
.join(" / ");
|
||||
},
|
||||
types() {
|
||||
if (!this.searchoptions.types)
|
||||
return [];
|
||||
if (!this.searchoptions.types) return [];
|
||||
if (Array.isArray(this.searchoptions.types))
|
||||
return this.searchoptions.types;
|
||||
return Object.keys(this.searchoptions.types);
|
||||
},
|
||||
typeLabels() {
|
||||
if (!this.searchoptions.types)
|
||||
return {};
|
||||
if (!this.searchoptions.types) return {};
|
||||
if (Array.isArray(this.searchoptions.types)) {
|
||||
return this.searchoptions.types.reduce((res, type) => {
|
||||
res[type] = type;
|
||||
return res
|
||||
return res;
|
||||
}, {});
|
||||
}
|
||||
return this.searchoptions.types;
|
||||
}
|
||||
},
|
||||
},
|
||||
template: /*html*/`
|
||||
template: /*html*/ `
|
||||
<form
|
||||
ref="searchform"
|
||||
class="d-flex me-3"
|
||||
@@ -92,80 +94,91 @@ export default {
|
||||
@focusin="searchfocusin"
|
||||
@focusout="searchfocusout"
|
||||
>
|
||||
<div
|
||||
ref="searchbox"
|
||||
class="h-100 input-group me-2 searchbar_searchbox"
|
||||
:class="showresult ? 'open' : 'closed'"
|
||||
<span
|
||||
v-if="isMobile"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target=".multi-collapse"
|
||||
aria-controls="header-searchbar-collapsible header-options-collapsible header-usermenu-collapsible"
|
||||
aria-expanded="false"
|
||||
class="d-flex flex-row align-items-center ps-3 pe-1"
|
||||
>
|
||||
<span class="input-group-text">
|
||||
<i class="fa-solid fa-magnifying-glass"></i>
|
||||
</span>
|
||||
<input
|
||||
ref="input"
|
||||
@keyup="search"
|
||||
@focus="showsearchresult"
|
||||
v-model="searchsettings.searchstr"
|
||||
class="form-control searchbar_input"
|
||||
type="search"
|
||||
:placeholder="$p.t('search/input_search_label', { types: searchTypesPlaceholder })"
|
||||
:aria-label="$p.t('search/input_search_label', { types: searchTypesPlaceholder })"
|
||||
>
|
||||
<button
|
||||
v-if="searchsettings.searchstr"
|
||||
type="button"
|
||||
class="searchbar_input_clear btn btn-outline-secondary"
|
||||
@click="clearInput"
|
||||
@focusin.stop
|
||||
>
|
||||
<i class="fas fa-close"></i>
|
||||
</button>
|
||||
<button
|
||||
v-if="showBtnSubmit"
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
:title="$p.t('search/submit')"
|
||||
:aria-label="$p.t('search/submit')"
|
||||
>
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
<button
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#searchSettings"
|
||||
aria-expanded="false"
|
||||
aria-controls="searchSettings"
|
||||
ref="settingsbutton"
|
||||
class="searchbar_setting_btn btn btn-secondary"
|
||||
type="button"
|
||||
:title="$p.t('search/button_filter_label')"
|
||||
:aria-label="$p.t('search/button_filter_label')"
|
||||
>
|
||||
<i class="fas fa-cog"></i>
|
||||
</button>
|
||||
</div>
|
||||
<i v-if="isSearchShownInMobileView" class="fa-solid fa-chevron-left"></i>
|
||||
<i v-else class="fa-solid fa-magnifying-glass"></i>
|
||||
</span>
|
||||
|
||||
<div v-show="showresult"
|
||||
class="searchbar_results" tabindex="-1">
|
||||
<div class="searchbar_results_scroller" ref="result">
|
||||
<div class="searchbar_results_wrapper" ref="results">
|
||||
<div v-if="searching">
|
||||
<i class="fas fa-spinner fa-spin fa-2x"></i>
|
||||
</div>
|
||||
<div v-else-if="this.error !== null">{{ error }}</div>
|
||||
<div v-else-if="searchresult.length < 1">{{ $p.t('search/error_no_results') }}</div>
|
||||
<template v-else v-for="res in searchresult">
|
||||
<component
|
||||
v-if="isValidRenderer(res.renderer)"
|
||||
:is="res.renderer"
|
||||
:mode="searchmode"
|
||||
:res="res"
|
||||
:actions="getActions(res)"
|
||||
@actionexecuted="hideresult"
|
||||
></component>
|
||||
<div v-else class="searchbar-result text-danger fw-bold">{{ $p.t('search/error_unknown_type', res) }}</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
:class="{'flex-grow-1': !isMobile, 'collapse multi-collapse collapse-horizontal': isMobile}"
|
||||
id="header-searchbar-collapsible"
|
||||
@[\`show.bs.collapse\`]="isSearchShownInMobileView = true"
|
||||
@[\`hidden.bs.collapse\`]="isSearchShownInMobileView = false"
|
||||
>
|
||||
<div
|
||||
:class="{open: showresult, closed: showresult, 'px-3': isMobile}"
|
||||
ref="searchbox"
|
||||
class="h-100 input-group me-2 searchbar_searchbox"
|
||||
:style="isMobile ? 'width: ' + getMaxWidthOfSearchbarInMobileView() : ''"
|
||||
>
|
||||
<span class="input-group-text">
|
||||
<i class="fa-solid fa-magnifying-glass color-white"></i>
|
||||
</span>
|
||||
<input
|
||||
ref="input"
|
||||
@keyup="search"
|
||||
@focus="showsearchresult"
|
||||
v-model="searchsettings.searchstr"
|
||||
class="form-control searchbar_input"
|
||||
type="search"
|
||||
:placeholder="$p.t('search/input_search_label', { types: searchTypesPlaceholder })"
|
||||
:aria-label="$p.t('search/input_search_label', { types: searchTypesPlaceholder })"
|
||||
>
|
||||
<button
|
||||
v-if="showBtnSubmit"
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
:title="$p.t('search/submit')"
|
||||
:aria-label="$p.t('search/submit')"
|
||||
>
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
<button
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#searchSettings"
|
||||
aria-expanded="false"
|
||||
aria-controls="searchSettings"
|
||||
ref="settingsbutton"
|
||||
class="searchbar_setting_btn btn btn-secondary"
|
||||
type="button"
|
||||
:title="$p.t('search/button_filter_label')"
|
||||
:aria-label="$p.t('search/button_filter_label')"
|
||||
>
|
||||
<i class="fas fa-filter"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div v-show="showresult"
|
||||
class="searchbar_results" tabindex="-1">
|
||||
<div class="searchbar_results_scroller" ref="result">
|
||||
<div class="searchbar_results_wrapper" ref="results">
|
||||
<div v-if="searching">
|
||||
<i class="fas fa-spinner fa-spin fa-2x"></i>
|
||||
</div>
|
||||
<div v-else-if="this.error !== null">{{ error }}</div>
|
||||
<div v-else-if="searchresult.length < 1">{{ $p.t('search/error_no_results') }}</div>
|
||||
<template v-else v-for="res in searchresult">
|
||||
<component
|
||||
v-if="isValidRenderer(res.renderer)"
|
||||
:is="res.renderer"
|
||||
:mode="searchmode"
|
||||
:res="res"
|
||||
:actions="getActions(res)"
|
||||
@actionexecuted="hideresult"
|
||||
></component>
|
||||
<div v-else class="searchbar-result text-danger fw-bold">{{ $p.t('search/error_unknown_type', res) }}</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="searchSettings"
|
||||
@@ -207,34 +220,42 @@ export default {
|
||||
</div>
|
||||
</form>
|
||||
`,
|
||||
watch:{
|
||||
'searchsettings.searchstr': function (newSearchValue) {
|
||||
if(this.searchoptions.origin){
|
||||
sessionStorage.setItem(`${this.searchoptions.origin}_searchstr`,newSearchValue);
|
||||
watch: {
|
||||
"searchsettings.searchstr": function (newSearchValue) {
|
||||
if (this.searchoptions.origin) {
|
||||
sessionStorage.setItem(
|
||||
`${this.searchoptions.origin}_searchstr`,
|
||||
newSearchValue,
|
||||
);
|
||||
}
|
||||
},
|
||||
'searchsettings.types'(newValue) {
|
||||
"searchsettings.types"(newValue) {
|
||||
if (Array.isArray(newValue) && newValue.length === 0) {
|
||||
this.searchsettings.types = [...this.types];
|
||||
}
|
||||
// stores the search types in the localstorage, only if the newValue is also an array
|
||||
if (Array.isArray(newValue) && this.searchoptions.origin) {
|
||||
localStorage.setItem(`${this.searchoptions.origin}_searchtypes`, JSON.stringify(newValue));
|
||||
localStorage.setItem(
|
||||
`${this.searchoptions.origin}_searchtypes`,
|
||||
JSON.stringify(newValue),
|
||||
);
|
||||
}
|
||||
this.search();
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.settingsDropdown = new bootstrap.Collapse(this.$refs.settings, {
|
||||
toggle: false
|
||||
toggle: false,
|
||||
});
|
||||
|
||||
if (!this.searchoptions.origin){
|
||||
console.warn("No origin defined in the searchoptions for the searchbar, please define the origin property in the searchbaroptions to allow reliable storage of searchstr and searchtypes accross applications.");
|
||||
if (!this.searchoptions.origin) {
|
||||
console.warn(
|
||||
"No origin defined in the searchoptions for the searchbar, please define the origin property in the searchbaroptions to allow reliable storage of searchstr and searchtypes accross applications.",
|
||||
);
|
||||
}
|
||||
},
|
||||
updated() {
|
||||
if(this.showresult) {
|
||||
if (this.showresult) {
|
||||
Vue.nextTick(() => {
|
||||
this.calcSearchResultHeight();
|
||||
});
|
||||
@@ -249,32 +270,34 @@ export default {
|
||||
getInitiallySelectedTypes() {
|
||||
let result = false;
|
||||
if (this.searchoptions.origin) {
|
||||
let localStorageValue = localStorage.getItem(`${this.searchoptions.origin}_searchtypes`);
|
||||
let localStorageValue = localStorage.getItem(
|
||||
`${this.searchoptions.origin}_searchtypes`,
|
||||
);
|
||||
if (localStorageValue) {
|
||||
result = JSON.parse(localStorageValue);
|
||||
}
|
||||
}
|
||||
if (result)
|
||||
return result;
|
||||
if (!this.searchoptions.types)
|
||||
return [];
|
||||
if (result) return result;
|
||||
if (!this.searchoptions.types) return [];
|
||||
if (Array.isArray(this.searchoptions.types))
|
||||
return [...this.searchoptions.types];
|
||||
return Object.keys(this.searchoptions.types);
|
||||
},
|
||||
getSearchStr: function(){
|
||||
if (!this.searchoptions.origin)
|
||||
return '';
|
||||
return sessionStorage.getItem(`${this.searchoptions.origin}_searchstr`) ?? '';
|
||||
getSearchStr: function () {
|
||||
if (!this.searchoptions.origin) return "";
|
||||
return (
|
||||
sessionStorage.getItem(
|
||||
`${this.searchoptions.origin}_searchstr`,
|
||||
) ?? ""
|
||||
);
|
||||
},
|
||||
checkSettingsVisibility: function(event) {
|
||||
checkSettingsVisibility: function (event) {
|
||||
// hides the settings collapsible if the user clicks somewhere else
|
||||
if (!this.$refs.settings.contains(event.target))
|
||||
{
|
||||
if (!this.$refs.settings.contains(event.target)) {
|
||||
this.settingsDropdown.hide();
|
||||
}
|
||||
},
|
||||
handleShowSettings: function() {
|
||||
handleShowSettings: function () {
|
||||
// adds the event listener checkSettingsVisibility only when the collapsible is shown
|
||||
document.addEventListener("click", this.checkSettingsVisibility);
|
||||
},
|
||||
@@ -282,183 +305,208 @@ export default {
|
||||
// removes the event listener checkSettingsVisibility when the collapsible is hidden
|
||||
document.removeEventListener("click", this.checkSettingsVisibility);
|
||||
},
|
||||
calcSearchResultHeight: function() {
|
||||
calcSearchResultHeight: function () {
|
||||
const rect = this.$refs.results.getBoundingClientRect();
|
||||
if( rect.height > 0 && rect.height < (window.innerHeight * 0.8) ) {
|
||||
this.$refs.result.style.height = Math.ceil(rect.height + 16) + 'px';
|
||||
if (rect.height > 0 && rect.height < window.innerHeight * 0.8) {
|
||||
this.$refs.result.style.height =
|
||||
Math.ceil(rect.height + 16) + "px";
|
||||
} else {
|
||||
this.$refs.result.style.height = Math.floor(window.innerHeight * 0.8) + 'px';
|
||||
this.$refs.result.style.height =
|
||||
Math.floor(window.innerHeight * 0.8) + "px";
|
||||
}
|
||||
},
|
||||
calcSearchResultExtent: function() {
|
||||
if(!this.showresult) {
|
||||
calcSearchResultExtent: function () {
|
||||
if (!this.showresult) {
|
||||
return;
|
||||
}
|
||||
if(this.searchoptions?.calcheightonly === undefined
|
||||
|| this.searchoptions.calcheightonly === false) {
|
||||
if (
|
||||
this.searchoptions?.calcheightonly === undefined ||
|
||||
this.searchoptions.calcheightonly === false
|
||||
) {
|
||||
var rect = this.$refs.searchbox.getBoundingClientRect();
|
||||
this.$refs.result.style.top = Math.floor(rect.bottom + 3) + 'px';
|
||||
this.$refs.result.style.right = Math.floor(rect.right) + 'px';
|
||||
this.$refs.result.style.width = Math.floor(rect.width) + 'px';
|
||||
this.$refs.result.style.top =
|
||||
Math.floor(rect.bottom + 3) + "px";
|
||||
this.$refs.result.style.right = Math.floor(rect.right) + "px";
|
||||
this.$refs.result.style.width = Math.floor(rect.width) + "px";
|
||||
}
|
||||
this.calcSearchResultHeight();
|
||||
},
|
||||
search: function() {
|
||||
if(this.searchoptions?.nolivesearch === true) return;
|
||||
this.calcSearchResultHeight();
|
||||
},
|
||||
search: function () {
|
||||
if (this.searchoptions?.nolivesearch === true) return;
|
||||
|
||||
this.abort();
|
||||
if( this.searchsettings.searchstr.length >= 2 ) {
|
||||
this.calcSearchResultExtent();
|
||||
this.searchtimer = setTimeout(
|
||||
this.callsearchapi,
|
||||
500
|
||||
);
|
||||
} else {
|
||||
this.showresult = false;
|
||||
}
|
||||
},
|
||||
abort() {
|
||||
if (this.searchtimer !== null) {
|
||||
clearTimeout(this.searchtimer);
|
||||
}
|
||||
if (this.abortController) {
|
||||
this.abortController.abort();
|
||||
this.abortController = null;
|
||||
}
|
||||
this.searchresult = [];
|
||||
},
|
||||
callsearchapi: function() {
|
||||
this.error = null;
|
||||
this.searchresult.splice(0, this.searchresult.length);
|
||||
this.searching = true;
|
||||
this.showsearchresult();
|
||||
if(this.searchsettings.types.length === 0) {
|
||||
this.error = this.$p.t('search/error_missing_type');
|
||||
this.searching = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.abortController)
|
||||
this.abortController.abort();
|
||||
this.abortController = new AbortController();
|
||||
|
||||
this.searchfunction(this.searchsettings, { timeout: 50000, signal: this.abortController.signal })
|
||||
.then(response=>{
|
||||
if (!response.data) {
|
||||
this.error = this.$p.t('search/error_general');
|
||||
} else {
|
||||
let res = response.data.map(el => el.data ? {...el, ...JSON.parse(el.data)} : el);
|
||||
this.lastQuery = response.meta.searchstring;
|
||||
if (this.searchoptions.mergeResults) {
|
||||
let counter = 0;
|
||||
let mergeTypes = [];
|
||||
let mergedType = 'merged-';
|
||||
let mergeKey = '';
|
||||
|
||||
switch (this.searchoptions.mergeResults) {
|
||||
case 'student':
|
||||
mergeTypes = ['student', 'prestudent'];
|
||||
mergedType += this.searchoptions.mergeResults;
|
||||
mergeKey = 'uid';
|
||||
break;
|
||||
case 'person':
|
||||
mergeTypes = ['person', 'employee', 'student', 'prestudent'];
|
||||
mergedType += this.searchoptions.mergeResults;
|
||||
mergeKey = 'person_id';
|
||||
break;
|
||||
}
|
||||
|
||||
if (mergeTypes.length) {
|
||||
res = Object.values(res.reduce((a, c) => {
|
||||
if (!mergeTypes.includes(c.renderer)) {
|
||||
a['nomerge' + counter++] = c;
|
||||
} else if (c[mergeKey] === null) {
|
||||
a['nomerge' + counter++] = c;
|
||||
} else if (a[c[mergeKey]] === undefined) {
|
||||
a[c[mergeKey]] = {
|
||||
rank: c.rank,
|
||||
renderer: mergedType,
|
||||
type: mergedType,
|
||||
list: [c]
|
||||
};
|
||||
} else {
|
||||
a[c[mergeKey]].list.push(c);
|
||||
if (c.rank > a[c[mergeKey]].rank)
|
||||
a[c[mergeKey]].rank = c.rank;
|
||||
}
|
||||
return a;
|
||||
}, {})).sort((a, b) => b.rank - a.rank);
|
||||
}
|
||||
}
|
||||
this.searchresult = res;
|
||||
this.searchmode = response.meta.mode;
|
||||
}
|
||||
this.searching = false;
|
||||
this.retry = 0;
|
||||
})
|
||||
.catch(error=> {
|
||||
if (error.code == "ERR_CANCELED") {
|
||||
return this.retry = 0;
|
||||
}
|
||||
if (error.code == "ECONNABORTED" && this.retry) {
|
||||
this.retry--;
|
||||
return this.callsearchapi();
|
||||
}
|
||||
|
||||
this.error = this.$p.t('search/error_general', error);
|
||||
this.searching = false;
|
||||
this.retry = 0;
|
||||
});
|
||||
},
|
||||
refreshsearch: function() {
|
||||
this.search();
|
||||
this.togglesettings();
|
||||
},
|
||||
hideresult: function() {
|
||||
this.showresult = false;
|
||||
window.removeEventListener('resize', this.calcSearchResultExtent);
|
||||
},
|
||||
showsearchresult: function() {
|
||||
if(this.searchoptions?.nolivesearch === true) return;
|
||||
|
||||
if( this.searchsettings.searchstr.length >= 2 ) {
|
||||
this.showresult = true;
|
||||
window.addEventListener('resize', this.calcSearchResultExtent);
|
||||
this.abort();
|
||||
if (this.searchsettings.searchstr.length >= 2) {
|
||||
this.calcSearchResultExtent();
|
||||
}
|
||||
},
|
||||
searchfocusin: function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if( this.hidetimer !== null ) {
|
||||
clearTimeout(this.hidetimer);
|
||||
}
|
||||
if (this.searchsettings.searchstr.length >= 2
|
||||
&& this.searchresult.length === 0) {
|
||||
this.searchtimer = setTimeout(this.callsearchapi, 500);
|
||||
} else {
|
||||
this.showresult = false;
|
||||
}
|
||||
},
|
||||
abort() {
|
||||
if (this.searchtimer !== null) {
|
||||
clearTimeout(this.searchtimer);
|
||||
}
|
||||
if (this.abortController) {
|
||||
this.abortController.abort();
|
||||
this.abortController = null;
|
||||
}
|
||||
this.searchresult = [];
|
||||
},
|
||||
callsearchapi: function () {
|
||||
this.error = null;
|
||||
this.searchresult.splice(0, this.searchresult.length);
|
||||
this.searching = true;
|
||||
this.showsearchresult();
|
||||
if (this.searchsettings.types.length === 0) {
|
||||
this.error = this.$p.t("search/error_missing_type");
|
||||
this.searching = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.abortController) this.abortController.abort();
|
||||
this.abortController = new AbortController();
|
||||
|
||||
this.searchfunction(this.searchsettings, {
|
||||
timeout: 50000,
|
||||
signal: this.abortController.signal,
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.data) {
|
||||
this.error = this.$p.t("search/error_general");
|
||||
} else {
|
||||
let res = response.data.map((el) =>
|
||||
el.data ? { ...el, ...JSON.parse(el.data) } : el,
|
||||
);
|
||||
this.lastQuery = response.meta.searchstring;
|
||||
if (this.searchoptions.mergeResults) {
|
||||
let counter = 0;
|
||||
let mergeTypes = [];
|
||||
let mergedType = "merged-";
|
||||
let mergeKey = "";
|
||||
|
||||
switch (this.searchoptions.mergeResults) {
|
||||
case "student":
|
||||
mergeTypes = ["student", "prestudent"];
|
||||
mergedType +=
|
||||
this.searchoptions.mergeResults;
|
||||
mergeKey = "uid";
|
||||
break;
|
||||
case "person":
|
||||
mergeTypes = [
|
||||
"person",
|
||||
"employee",
|
||||
"student",
|
||||
"prestudent",
|
||||
];
|
||||
mergedType +=
|
||||
this.searchoptions.mergeResults;
|
||||
mergeKey = "person_id";
|
||||
break;
|
||||
}
|
||||
|
||||
if (mergeTypes.length) {
|
||||
res = Object.values(
|
||||
res.reduce((a, c) => {
|
||||
if (!mergeTypes.includes(c.renderer)) {
|
||||
a["nomerge" + counter++] = c;
|
||||
} else if (c[mergeKey] === null) {
|
||||
a["nomerge" + counter++] = c;
|
||||
} else if (
|
||||
a[c[mergeKey]] === undefined
|
||||
) {
|
||||
a[c[mergeKey]] = {
|
||||
rank: c.rank,
|
||||
renderer: mergedType,
|
||||
type: mergedType,
|
||||
list: [c],
|
||||
};
|
||||
} else {
|
||||
a[c[mergeKey]].list.push(c);
|
||||
if (c.rank > a[c[mergeKey]].rank)
|
||||
a[c[mergeKey]].rank = c.rank;
|
||||
}
|
||||
return a;
|
||||
}, {}),
|
||||
).sort((a, b) => b.rank - a.rank);
|
||||
}
|
||||
}
|
||||
this.searchresult = res;
|
||||
this.searchmode = response.meta.mode;
|
||||
}
|
||||
this.searching = false;
|
||||
this.retry = 0;
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.code == "ERR_CANCELED") {
|
||||
return (this.retry = 0);
|
||||
}
|
||||
if (error.code == "ECONNABORTED" && this.retry) {
|
||||
this.retry--;
|
||||
return this.callsearchapi();
|
||||
}
|
||||
|
||||
this.error = this.$p.t("search/error_general", error);
|
||||
this.searching = false;
|
||||
this.retry = 0;
|
||||
});
|
||||
},
|
||||
refreshsearch: function () {
|
||||
this.search();
|
||||
this.togglesettings();
|
||||
},
|
||||
hideresult: function () {
|
||||
this.showresult = false;
|
||||
window.removeEventListener("resize", this.calcSearchResultExtent);
|
||||
},
|
||||
showsearchresult: function () {
|
||||
if (this.searchoptions?.nolivesearch === true) return;
|
||||
|
||||
if (this.searchsettings.searchstr.length >= 2) {
|
||||
this.showresult = true;
|
||||
window.addEventListener("resize", this.calcSearchResultExtent);
|
||||
this.calcSearchResultExtent();
|
||||
}
|
||||
},
|
||||
searchfocusin: function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (this.hidetimer !== null) {
|
||||
clearTimeout(this.hidetimer);
|
||||
}
|
||||
if (
|
||||
this.searchsettings.searchstr.length >= 2 &&
|
||||
this.searchresult.length === 0
|
||||
) {
|
||||
this.search();
|
||||
}
|
||||
},
|
||||
searchfocusout: function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.hidetimer = setTimeout(
|
||||
this.hideresult,
|
||||
100
|
||||
);
|
||||
},
|
||||
dash2camelCase(string) {
|
||||
return string.replace(/-([a-z])/g, g => g[1].toUpperCase());
|
||||
},
|
||||
isValidRenderer(renderer) {
|
||||
const camelCaseRenderer = this.dash2camelCase(renderer);
|
||||
return Object.keys(this.$.components).includes(camelCaseRenderer);
|
||||
},
|
||||
},
|
||||
searchfocusout: function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.hidetimer = setTimeout(this.hideresult, 100);
|
||||
},
|
||||
dash2camelCase(string) {
|
||||
return string.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
|
||||
},
|
||||
isValidRenderer(renderer) {
|
||||
const camelCaseRenderer = this.dash2camelCase(renderer);
|
||||
return Object.keys(this.$.components).includes(camelCaseRenderer);
|
||||
},
|
||||
getActions(res) {
|
||||
let actions = this.searchoptions.actions[this.dash2camelCase(res.renderer)];
|
||||
let actions =
|
||||
this.searchoptions.actions[this.dash2camelCase(res.renderer)];
|
||||
if (actions) {
|
||||
return actions;
|
||||
}
|
||||
return this.searchoptions.actions[res.type];
|
||||
}
|
||||
}
|
||||
},
|
||||
getMaxWidthOfSearchbarInMobileView() {
|
||||
// body width - hardcoded chevron width; necessary for accurate collapse transition transition
|
||||
return (
|
||||
document.querySelector("body").getBoundingClientRect().width -
|
||||
27 +
|
||||
"px"
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -111,7 +111,7 @@ export function useEventLoader(rangeInterval, getPromiseFunc) {
|
||||
return mergePromiseArr(getPromiseFunc(start, end), result);
|
||||
};
|
||||
|
||||
const reload = () => {
|
||||
Vue.watchEffect(() => {
|
||||
const range = Vue.toValue(rangeInterval);
|
||||
if (!(range instanceof luxon.Interval))
|
||||
return;
|
||||
@@ -132,18 +132,7 @@ export function useEventLoader(rangeInterval, getPromiseFunc) {
|
||||
}
|
||||
})
|
||||
});
|
||||
};
|
||||
})
|
||||
|
||||
Vue.watchEffect(reload);
|
||||
|
||||
const reset = () => {
|
||||
loading_id = 0;
|
||||
events.value = [];
|
||||
loadingEvents.value = [];
|
||||
eventsLoaded.splice(0, eventsLoaded.length);
|
||||
|
||||
reload();
|
||||
}
|
||||
|
||||
return { events: allEvents, lv, reset }
|
||||
return { events: allEvents, lv }
|
||||
}
|
||||
@@ -94,7 +94,6 @@ require_once('dbupdate_3.4/71399_dashboard_update_widget_paths.php');
|
||||
require_once('dbupdate_3.4/71645_studvw_messagetab_ladezeit.php');
|
||||
require_once('dbupdate_3.4/71566_studienordnungsdokument_neuer_organisationseinheitstyp_programm.php');
|
||||
require_once('dbupdate_3.4/70376_lohnguide.php');
|
||||
require_once('dbupdate_3.4/76150_perm_other_lv_plan.php');
|
||||
|
||||
// *** Pruefung und hinzufuegen der neuen Attribute und Tabellen
|
||||
echo '<H2>Pruefe Tabellen und Attribute!</H2>';
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
/* Copyright (C) 2017 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 2 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* Authors: Harald Bamberger <harald.bamberger@technikum-wien.at>,
|
||||
*
|
||||
* Beschreibung:
|
||||
* Permission basis/other_lv_plan
|
||||
*/
|
||||
if (! defined('DB_NAME')) exit('No direct script access allowed');
|
||||
|
||||
// Add permission: basis/gehaelter
|
||||
if($result = @$db->db_query("SELECT 1 FROM system.tbl_berechtigung WHERE berechtigung_kurzbz = 'basis/other_lv_plan';"))
|
||||
{
|
||||
if($db->db_num_rows($result) == 0)
|
||||
{
|
||||
$qry = "INSERT INTO system.tbl_berechtigung(berechtigung_kurzbz, beschreibung) VALUES('basis/other_lv_plan', 'Permission holder can view other users timetables (LV plans)');";
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
{
|
||||
echo '<strong>system.tbl_berechtigung '.$db->db_last_error().'</strong><br>';
|
||||
}
|
||||
else
|
||||
{
|
||||
echo 'system.tbl_berechtigung: Added permission "basis/other_lv_plan"<br>';
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-287
@@ -29562,8 +29562,7 @@ array(
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
), array(
|
||||
'app' => 'core',
|
||||
'category' => 'profil',
|
||||
'phrase' => 'sem_short',
|
||||
@@ -29583,126 +29582,6 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'profil',
|
||||
'phrase' => 'calendar_sync',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Persönlichen LV-Plan abonnieren',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Subscribe to personal schedule',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'profil',
|
||||
'phrase' => 'calendar_sync_instructions',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Anleitung LV-Plan Synchronisation',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Instructions for synchronizing your schedule',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'profil',
|
||||
'phrase' => 'calendar_sync_cal_dav',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'CalDAV URL (Android, Thunderbird, CalDAV-Synchronizer)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'CalDAV URL (Android, Thunderbird, CalDAV-Synchronizer)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'profil',
|
||||
'phrase' => 'calendar_sync_cal_dav_principal',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'CalDAV Principal URL (MacOS, iOS)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'CalDAV Principal URL (MacOS, iOS)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'profil',
|
||||
'phrase' => 'calendar_sync_i_cal',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'iCAL URL (Google)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'iCAL URL (Google)',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'profil',
|
||||
'phrase' => 'calendar_sync_clipboard_copy_confirmation',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'URL in die Zwischenablage kopiert.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'URL copied to clipboard.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
//Profil Phrasen ende
|
||||
// LvPlan Phrasen start
|
||||
array(
|
||||
@@ -58298,171 +58177,6 @@ I have been informed that I am under no obligation to consent to the transmissio
|
||||
)
|
||||
),
|
||||
// ### Phrases Dashboard Admin END
|
||||
|
||||
// ### LvPlanStgOrg START ###
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'LvPlan',
|
||||
'phrase' => 'noStgProvided',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'kein Studiengang hinterlegt',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'no degree-program provided',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'LvPlan',
|
||||
'phrase' => 'headerLvPlanLvVerband',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Lv-Plan Lehrverband',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Course-Plan Teaching Association',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'LvPlan',
|
||||
'phrase' => 'chooseStg',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Studiengang auswählen...',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Select a degree-program...',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'LvPlan',
|
||||
'phrase' => 'loadLvPlan',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Lehrverband laden',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Load Course-Plan',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'LvPlan',
|
||||
'phrase' => 'backToDropdown',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Zurück zum Auswahl-Dropdown',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Back to Dropdown',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'LvPlan',
|
||||
'phrase' => 'error_SemMissing',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Semester wählen',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Select a semester',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'LvPlan',
|
||||
'phrase' => 'error_VerbandMissing',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Verband wählen',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Select a verband',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
// ### LvPlanStgOrg END ###
|
||||
// DMS-Link Phrasen Start
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'DMS-Link',
|
||||
'phrase' => 'lvplanSyncFAQ',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => '7188',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => '7188',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
// DMS-Link Phrasen End
|
||||
);
|
||||
|
||||
|
||||
|
||||
@@ -227,8 +227,7 @@ if (isset($_GET['sendform']))
|
||||
<table class="tablesorter" id="t1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><button type="button" class="resetsaved" title="Reset Filter">Reset Filter</button>
|
||||
<span class="tooltip"><img src="../../skin/images/information.png" height="20px" name="infoicon"/>
|
||||
<th><span class="tooltip"><img src="../../skin/images/information.png" height="20px" name="infoicon"/>
|
||||
'.$tooltiptext.'
|
||||
</span>
|
||||
</th>
|
||||
@@ -365,10 +364,9 @@ if (isset($_GET['sendform']))
|
||||
$("#t1").tablesorter(
|
||||
{
|
||||
sortList: [[3,0]],
|
||||
widgets: ["saveSort", "zebra", "filter", "stickyHeaders"],
|
||||
widgets: ["zebra", "filter", "stickyHeaders"],
|
||||
headers: { 0: { filter: false, sorter: false }},
|
||||
widgetOptions : { filter_saveFilters : true,
|
||||
filter_functions : {
|
||||
widgetOptions : { filter_functions : {
|
||||
// Add select menu to this column
|
||||
8 : {
|
||||
"True" : function(e, n, f, i, $r, c, data) { return /t/.test(e); },
|
||||
@@ -383,13 +381,6 @@ if (isset($_GET['sendform']))
|
||||
"False" : function(e, n, f, i, $r, c, data) { return /f/.test(e); }
|
||||
}
|
||||
}}
|
||||
});
|
||||
|
||||
$('.resetsaved').click(function()
|
||||
{
|
||||
$("#t1").trigger("filterReset");
|
||||
location.reload(forceGet);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -588,9 +588,7 @@ if(isset($_POST['testergebnisanzeigen']) && isset($_POST['prestudent_id']))
|
||||
{
|
||||
if(is_numeric($_POST['prestudent_id']) && $_POST['prestudent_id']!='')
|
||||
{
|
||||
$qry="SELECT nachname,vorname,person_id,prestudent_id,tbl_pruefling.pruefling_id,
|
||||
tbl_pruefling_frage.begintime,bezeichnung,kurzbz,tbl_frage.nummer,level,
|
||||
tbl_vorschlag.nummer as antwortnummer, tbl_vorschlag.punkte, tbl_frage.frage_id
|
||||
$qry="SELECT nachname,vorname,person_id,prestudent_id,tbl_pruefling.pruefling_id,tbl_pruefling_frage.begintime,bezeichnung,kurzbz,tbl_frage.nummer,level, tbl_vorschlag.nummer as antwortnummer, tbl_vorschlag.punkte
|
||||
FROM testtool.tbl_antwort
|
||||
JOIN testtool.tbl_vorschlag USING(vorschlag_id)
|
||||
JOIN testtool.tbl_frage USING (frage_id)
|
||||
@@ -617,7 +615,6 @@ if(isset($_POST['testergebnisanzeigen']) && isset($_POST['prestudent_id']))
|
||||
<th>Level</th>
|
||||
<th>Antwort #</th>
|
||||
<th>Punkte</th>
|
||||
<th>FrageID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
@@ -635,7 +632,6 @@ if(isset($_POST['testergebnisanzeigen']) && isset($_POST['prestudent_id']))
|
||||
echo "<td>$row->level</td>";
|
||||
echo "<td>$row->antwortnummer</td>";
|
||||
echo "<td>$row->punkte</td>";
|
||||
echo "<td>$row->frage_id</td>";
|
||||
echo '</tr>';
|
||||
}
|
||||
echo '</tbody></table>';
|
||||
|
||||
@@ -837,25 +837,6 @@ if(isset($_GET['excel']))
|
||||
<script src="../../vendor/fgelinas/timepicker/jquery.ui.timepicker.js" type="text/javascript" ></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$.tablesorter.addParser({
|
||||
id: "customDate",
|
||||
is: function(s) {
|
||||
//return false;
|
||||
//use the above line if you don\'t want table sorter to auto detected this parser
|
||||
// match dd.mm.yyyy e.g. 01.01.2001 as regex
|
||||
//return /\d{1,4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2} .*/.test(s);
|
||||
return /\d{1,2}.\d{1,2}.\d{1,4}.*/.test(s);
|
||||
},
|
||||
// replace regex-wildcards and return new date
|
||||
format: function(s) {
|
||||
s = s.replace(/\-/g," ");
|
||||
s = s.replace(/:/g," ");
|
||||
s = s.replace(/\./g," ");
|
||||
s = s.split(" ");
|
||||
return $.tablesorter.formatFloat(new Date(s[2], s[1]-1, s[0]).getTime());
|
||||
},
|
||||
type: "numeric"
|
||||
});
|
||||
$(document).ready(function()
|
||||
{
|
||||
// Check, ob Räume zugeteilt sind oder max_teilnehmer gesetzt ist, wenn "öffentlich" gesetzt wird
|
||||
@@ -1026,7 +1007,7 @@ if(isset($_GET['excel']))
|
||||
{
|
||||
widgets: ["zebra", "filter", "stickyHeaders"],
|
||||
sortList: [[2,0],[3,0]],
|
||||
headers: {0: { sorter: false},10: { sorter: "customDate"},11: { sorter: "customDate"}},
|
||||
headers: {0: { sorter: false}},
|
||||
widgetOptions: {filter_cssFilter: [
|
||||
"filter_clm_null",
|
||||
"filter_clm_prestudent_id",
|
||||
@@ -1039,7 +1020,6 @@ if(isset($_GET['excel']))
|
||||
"filter_clm_studienplan",
|
||||
"filter_clm_einstiegssemester",
|
||||
"filter_clm_geburtsdatum",
|
||||
"filter_clm_anmeldedatum",
|
||||
"filter_clm_email",
|
||||
"filter_clm_absolviert"]}
|
||||
});
|
||||
@@ -1092,7 +1072,6 @@ if(isset($_GET['excel']))
|
||||
'clm_studienplan',
|
||||
'clm_einstiegssemester',
|
||||
'clm_geburtsdatum',
|
||||
"filter_clm_anmeldedatum",
|
||||
'clm_email',
|
||||
'clm_absolviert'];
|
||||
for (var i in arr)
|
||||
@@ -2718,8 +2697,7 @@ if($reihungstest_id!='')
|
||||
WHERE prestudent_id = tbl_prestudent.prestudent_id
|
||||
AND status_kurzbz = 'Interessent'
|
||||
) LIMIT 1
|
||||
) AS orgform_kurzbz,
|
||||
tbl_rt_person.anmeldedatum
|
||||
) AS orgform_kurzbz
|
||||
FROM PUBLIC.tbl_rt_person
|
||||
JOIN PUBLIC.tbl_person USING (person_id)
|
||||
JOIN PUBLIC.tbl_reihungstest rt ON (rt_id = rt.reihungstest_id)
|
||||
@@ -2808,7 +2786,6 @@ if($reihungstest_id!='')
|
||||
echo '<div id="clm_studienplan" class="active" onclick="hideColumn(\'clm_studienplan\')">Studienplan</div>';
|
||||
echo '<div id="clm_einstiegssemester" class="active" onclick="hideColumn(\'clm_einstiegssemester\')">Einstiegssemester</div>';
|
||||
echo '<div id="clm_geburtsdatum" class="active" onclick="hideColumn(\'clm_geburtsdatum\')">Geburtsdatum</div>';
|
||||
echo '<div id="clm_anmeldedatum" class="active" onclick="hideColumn(\'clm_anmeldedatum\')">Geburtsdatum</div>';
|
||||
echo '<div id="clm_email" class="active" onclick="hideColumn(\'clm_email\')">EMail</div>';
|
||||
echo '<div id="clm_absolviert" class="active" onclick="hideColumn(\'clm_absolviert\')">Absolvierte Tests <span class="wait"></span></div>';
|
||||
//echo '<div id="clm_ergebnis" class="active" onclick="hideColumn(\'clm_ergebnis\')">Ergebnis <span class="wait"></span></div>';
|
||||
@@ -2850,7 +2827,6 @@ if($reihungstest_id!='')
|
||||
<th style="display: table-cell" class="clm_studienplan">Studienplan</th>
|
||||
<th style="display: table-cell" class="clm_einstiegssemester">Einstiegssemester</th>
|
||||
<th style="display: table-cell" class="clm_geburtsdatum">Geburtsdatum</th>
|
||||
<th style="display: table-cell" class="clm_anmeldedatum">Anmeldedatum</th>
|
||||
<th style="display: table-cell" class="clm_email">EMail</th>
|
||||
<th style="display: table-cell" class="clm_absolviert">bereits absolvierte Verfahren</th>
|
||||
<!--<th style="display: table-cell" class="clm_ergebnis">Ergebnis</th>
|
||||
@@ -2970,7 +2946,6 @@ if($reihungstest_id!='')
|
||||
<td style="display: table-cell" class="clm_studienplan">'.$db->convert_html_chars($studienplan_bezeichnung).' ('.$row->studienplan_id.')</td>
|
||||
<td style="display: table-cell" class="clm_einstiegssemester">'.$db->convert_html_chars($row->ausbildungssemester).'</td>
|
||||
<td style="display: table-cell" class="clm_geburtsdatum">'.$db->convert_html_chars($row->gebdatum!=''?$datum_obj->convertISODate($row->gebdatum):' ').'</td>
|
||||
<td style="display: table-cell" class="clm_anmeldedatum">'.$db->convert_html_chars($row->anmeldedatum!=''?$datum_obj->convertISODate($row->anmeldedatum):' ').'</td>
|
||||
<td style="display: table-cell; text-align: center" class="clm_email"><a href="mailto:'.$db->convert_html_chars($row->email).'"><img src="../../skin/images/button_mail.gif" name="mail"></a></td>
|
||||
<td style="display: table-cell;" class="clm_absolviert">'.$rt_in_anderen_stg.'</td>
|
||||
</tr>';
|
||||
@@ -3034,7 +3009,6 @@ if($reihungstest_id!='')
|
||||
<th style="display: table-cell" class="clm_studienplan">Studienplan</th>
|
||||
<th style="display: table-cell" class="clm_einstiegssemester">Einstiegssemester</th>
|
||||
<th style="display: table-cell" class="clm_geburtsdatum">Geburtsdatum</th>
|
||||
<th style="display: table-cell" class="clm_anmeldedatum">Anmeldedatum</th>
|
||||
<th style="display: table-cell" class="clm_email">EMail</th>
|
||||
<th style="display: table-cell" class="clm_absolviert">bereits absolvierte Verfahren</th>
|
||||
<!--<th style="display: table-cell" class="clm_ergebnis">Ergebnis</th>
|
||||
@@ -3154,7 +3128,6 @@ if($reihungstest_id!='')
|
||||
<td style="display: table-cell" class="clm_studienplan">'.$db->convert_html_chars($studienplan_bezeichnung).' ('.$row->studienplan_id.')</td>
|
||||
<td style="display: table-cell" class="clm_einstiegssemester">'.$db->convert_html_chars($row->ausbildungssemester).'</td>
|
||||
<td style="display: table-cell" class="clm_geburtsdatum">'.$db->convert_html_chars($row->gebdatum!=''?$datum_obj->convertISODate($row->gebdatum):' ').'</td>
|
||||
<td style="display: table-cell" class="clm_anmeldedatum">'.$db->convert_html_chars($row->anmeldedatum!=''?$datum_obj->convertISODate($row->anmeldedatum):' ').'</td>
|
||||
<td style="display: table-cell; text-align: center" class="clm_email"><a href="mailto:'.$db->convert_html_chars($row->email).'"><img src="../../skin/images/button_mail.gif" name="mail"></a></td>
|
||||
<td style="display: table-cell;" class="clm_absolviert">'.$rt_in_anderen_stg.'</td>';
|
||||
/*echo '<td style="display: table-cell; align: right" class="clm_ergebnis">'.($rtergebnis==0?'-':number_format($rtergebnis,2,'.','')).' %</td>
|
||||
|
||||
Reference in New Issue
Block a user