mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-10-12 15:04:04 +00:00
Conflicts resolved
This commit is contained in:
@@ -16,25 +16,54 @@ class Tempus extends Auth_Controller
|
||||
|
||||
// Load Libraries
|
||||
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
|
||||
|
||||
|
||||
// Load Config
|
||||
$this->load->config('calendar');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function _remap()
|
||||
public function index()
|
||||
{
|
||||
$this->_loadView();
|
||||
}
|
||||
|
||||
public function sync()
|
||||
{
|
||||
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
|
||||
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
|
||||
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
|
||||
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
|
||||
$this->load->model('ressource/Kalenderstatus_model', 'KalenderStatusModel');
|
||||
|
||||
$this->OrganisationseinheitModel->addJoin('tbl_studiengang', 'oe_kurzbz', 'LEFT');
|
||||
|
||||
$this->OrganisationseinheitModel->addSelect('public.tbl_organisationseinheit.organisationseinheittyp_kurzbz,
|
||||
public.tbl_organisationseinheit.bezeichnung,
|
||||
public.tbl_studiengang.studiengang_kz,
|
||||
public.tbl_organisationseinheit.oe_kurzbz,
|
||||
tbl_studiengang.typ,
|
||||
COALESCE(public.tbl_studiengang.bezeichnung, \'\') as stgbezeichnung');
|
||||
$this->OrganisationseinheitModel->addOrder('tbl_organisationseinheit.aktiv', 'DESC');
|
||||
$this->OrganisationseinheitModel->addOrder('tbl_organisationseinheit.organisationseinheittyp_kurzbz');
|
||||
$organisationen = getData($this->OrganisationseinheitModel->loadWhere(array("tbl_organisationseinheit.aktiv" => true)));
|
||||
|
||||
|
||||
$this->StudiensemesterModel->addOrder('start', 'DESC');
|
||||
$studiensemestern = getData($this->StudiensemesterModel->load());
|
||||
|
||||
$this->_loadView(array('organisationen' => $organisationen, 'studiensemestern' => $studiensemestern));
|
||||
}
|
||||
|
||||
private function _loadView($extraVariables = [])
|
||||
{
|
||||
$this->load->view('Tempus', [
|
||||
'permissions' => [
|
||||
'admin' => $this->permissionlib->isBerechtigt('admin')
|
||||
'admin' => $this->permissionlib->isBerechtigt('admin'),
|
||||
'stundenraster' => $this->permissionlib->isBerechtigt('basis/tempus_stundenraster'),
|
||||
],
|
||||
'variables' => [
|
||||
'variables' => array_merge([
|
||||
'semester_aktuell' => $this->variablelib->getVar('semester_aktuell'),
|
||||
'timezone' => $this->config->item('timezone')
|
||||
]
|
||||
], $extraVariables)
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,10 @@ class Config extends FHCAPI_Controller
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'get' => ['admin:r', 'assistenz:r'],
|
||||
'getHeader' => ['admin:r', 'assistenz:r'],
|
||||
'set' => ['admin:r', 'assistenz:r'],
|
||||
'updateCollision' => ['admin:r', 'assistenz:r'],
|
||||
'get' => ['admin:r', 'assistenz:rw', 'lehre/lvplan:rw'],
|
||||
'getHeader' => ['admin:r', 'assistenz:rw', 'lehre/lvplan:rw'],
|
||||
'set' => ['admin:r', 'assistenz:rw', 'lehre/lvplan:rw'],
|
||||
'updateCollision' => ['admin:r', 'assistenz:rw', 'lehre/lvplan:rw'],
|
||||
]);
|
||||
|
||||
// Load Phrases
|
||||
@@ -32,7 +32,17 @@ class Config extends FHCAPI_Controller
|
||||
{
|
||||
$config = [];
|
||||
|
||||
$result = $this->_ci->VariableModel->getVariables(getAuthUID(), ['ignore_kollision', 'kollision_student', 'ignore_reservierung', 'ignore_zeitsperre', 'ignore_resources_collisions']);
|
||||
$var_array = array(
|
||||
'ignore_kollision',
|
||||
'kollision_student',
|
||||
'ignore_reservierung',
|
||||
'ignore_zeitsperre',
|
||||
'ignore_resources_collisions',
|
||||
'roomless_planning',
|
||||
'priority_room_planning',
|
||||
'dialog_room_planning'
|
||||
);
|
||||
$result = $this->_ci->VariableModel->getVariables(getAuthUID(), $var_array);
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
$config['ignore_kollision'] = [
|
||||
@@ -67,6 +77,25 @@ class Config extends FHCAPI_Controller
|
||||
"value" => ($data['ignore_resources_collisions'] ?? 'false') === 'true'
|
||||
];
|
||||
|
||||
$config['roomless_planning'] = [
|
||||
"type" => "checkbox",
|
||||
"label" => $this->p->t('ui', 'roomless_planning'),
|
||||
"value" => ($data['roomless_planning'] ?? 'false') === 'true'
|
||||
];
|
||||
|
||||
$config['priority_room_planning'] = [
|
||||
"type" => "checkbox",
|
||||
"label" => $this->p->t('ui', 'priority_room_planning'),
|
||||
"value" => ($data['priority_room_planning'] ?? 'false') === 'true'
|
||||
];
|
||||
|
||||
$config['dialog_room_planning'] = [
|
||||
"type" => "checkbox",
|
||||
"label" => $this->p->t('ui', 'dialog_room_planning'),
|
||||
"value" => ($data['dialog_room_planning'] ?? 'false') === 'true'
|
||||
];
|
||||
|
||||
|
||||
$this->terminateWithSuccess($config);
|
||||
}
|
||||
public function getHeader()
|
||||
@@ -92,31 +121,26 @@ class Config extends FHCAPI_Controller
|
||||
|
||||
public function set()
|
||||
{
|
||||
$this->_ci->VariableModel->setVariable(
|
||||
getAuthUID(),
|
||||
$configs = array(
|
||||
'ignore_kollision',
|
||||
$this->input->post('ignore_kollision') === true ? 'true' : 'false'
|
||||
);
|
||||
$this->_ci->VariableModel->setVariable(
|
||||
getAuthUID(),
|
||||
'kollision_student',
|
||||
$this->input->post('kollision_student') === true ? 'true' : 'false'
|
||||
);
|
||||
$this->_ci->VariableModel->setVariable(
|
||||
getAuthUID(),
|
||||
'ignore_reservierung',
|
||||
$this->input->post('ignore_reservierung') === true ? 'true' : 'false'
|
||||
);
|
||||
$this->_ci->VariableModel->setVariable(
|
||||
getAuthUID(),
|
||||
'ignore_zeitsperre',
|
||||
$this->input->post('ignore_zeitsperre') === true ? 'true' : 'false'
|
||||
);
|
||||
$this->_ci->VariableModel->setVariable(
|
||||
getAuthUID(),
|
||||
'ignore_resources_collisions',
|
||||
$this->input->post('ignore_resources_collisions') === true ? 'true' : 'false'
|
||||
'roomless_planning',
|
||||
'priority_room_planning',
|
||||
'dialog_room_planning'
|
||||
);
|
||||
|
||||
foreach ($configs as $config)
|
||||
{
|
||||
$this->_ci->VariableModel->setVariable(
|
||||
getAuthUID(),
|
||||
$config,
|
||||
$this->input->post($config) === true ? 'true' : 'false'
|
||||
);
|
||||
}
|
||||
|
||||
$this->terminateWithSuccess();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
class Coursepicker extends FHCAPI_Controller
|
||||
{
|
||||
private $_ci;
|
||||
|
||||
const ALLOWED_COURSE_FILTER = ['uid', 'stg'];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'search' => self::PERM_LOGGED,
|
||||
'getByStg' => self::PERM_LOGGED
|
||||
'getCourses' => 'lehre/lvplan:rw',
|
||||
]);
|
||||
|
||||
$this->_ci = &get_instance();
|
||||
@@ -22,88 +24,40 @@ class Coursepicker extends FHCAPI_Controller
|
||||
$this->loadPhrases(['ui']);
|
||||
}
|
||||
|
||||
public function search()
|
||||
{
|
||||
$query = $this->input->get('query');
|
||||
if (is_null($query))
|
||||
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
$query_words = explode(' ', $query);
|
||||
|
||||
//TODO Where weiter anpassen z.B. Fachbereich
|
||||
$this->_ci->LehreinheitModel->addSelect('tbl_lehreinheit.lehreinheit_id,
|
||||
tbl_lehreinheit.lvnr,
|
||||
tbl_lehreinheit.lehrfach_id,
|
||||
lehrfach.kurzbz AS lehrfach,
|
||||
lehrfach.bezeichnung AS lehrfach_bez,
|
||||
lehrfach.farbe AS lehrfach_farbe,
|
||||
tbl_lehreinheit.lehrform_kurzbz AS lehrform,
|
||||
lema.mitarbeiter_uid AS lektor_uid,
|
||||
tbl_mitarbeiter.kurzbz AS lektor,
|
||||
tbl_studiengang.studiengang_kz,
|
||||
upper(tbl_studiengang.typ::character varying::text || tbl_studiengang.kurzbz::text) AS studiengang,
|
||||
lvb.semester,
|
||||
lvb.verband,
|
||||
lvb.gruppe,
|
||||
lvb.gruppe_kurzbz,
|
||||
tbl_lehreinheit.raumtyp,
|
||||
tbl_lehreinheit.raumtypalternativ,
|
||||
tbl_lehreinheit.stundenblockung,
|
||||
tbl_lehreinheit.wochenrythmus,
|
||||
lema.semesterstunden,
|
||||
lema.planstunden,
|
||||
tbl_lehreinheit.start_kw,
|
||||
tbl_lehreinheit.anmerkung,
|
||||
tbl_lehreinheit.studiensemester_kurzbz');
|
||||
|
||||
$this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehreinheitmitarbeiter lema', 'tbl_lehreinheit.lehreinheit_id = lema.lehreinheit_id');
|
||||
$this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehreinheitgruppe lvb', 'tbl_lehreinheit.lehreinheit_id = lvb.lehreinheit_id');
|
||||
$this->_ci->LehreinheitModel->addJoin('public.tbl_studiengang', 'lvb.studiengang_kz = tbl_studiengang.studiengang_kz');
|
||||
$this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrveranstaltung lehrfach', 'tbl_lehreinheit.lehrfach_id = lehrfach.lehrveranstaltung_id');
|
||||
$this->_ci->LehreinheitModel->addJoin('public.tbl_mitarbeiter', 'lema.mitarbeiter_uid = tbl_mitarbeiter.mitarbeiter_uid');
|
||||
$this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrform', 'tbl_lehrform.lehrform_kurzbz = tbl_lehreinheit.lehrform_kurzbz');
|
||||
|
||||
$this->_ci->MitarbeiterModel->db->group_start();
|
||||
|
||||
foreach ($query_words as $word)
|
||||
{
|
||||
$this->_ci->LehreinheitModel->db->group_start();
|
||||
$this->_ci->LehreinheitModel->db->where('lema.mitarbeiter_uid ILIKE', "%" . $word . "%");
|
||||
$this->_ci->LehreinheitModel->db->or_where('lvb.gruppe_kurzbz ILIKE', "%" . $word . "%");
|
||||
$this->_ci->LehreinheitModel->db->or_where('tbl_studiengang.kurzbzlang ILIKE', "%" . $word . "%");
|
||||
$this->_ci->LehreinheitModel->db->or_where('lvb.verband ILIKE', "%" . $word . "%");
|
||||
$this->_ci->LehreinheitModel->db->or_where('lvb.gruppe ILIKE', "%" . $word . "%");
|
||||
$this->_ci->LehreinheitModel->db->or_where('lehrfach.bezeichnung ILIKE', "%" . $word . "%");
|
||||
|
||||
if (is_numeric($word))
|
||||
{
|
||||
$this->_ci->LehreinheitModel->db->or_where('tbl_studiengang.studiengang_kz', $word);
|
||||
$this->_ci->LehreinheitModel->db->or_where('lvb.semester', $word);
|
||||
}
|
||||
$this->_ci->LehreinheitModel->db->group_end();
|
||||
|
||||
}
|
||||
$this->_ci->LehreinheitModel->db->group_end();
|
||||
$this->_ci->LehreinheitModel->db->where('tbl_lehreinheit.studiensemester_kurzbz = \'SS2025\'');
|
||||
$this->_ci->LehreinheitModel->db->where(array('tbl_lehrform.verplanen' => true));
|
||||
|
||||
$result = $this->_ci->LehreinheitModel->load();
|
||||
|
||||
$this->terminateWithSuccess(hasData($result) ? getData($result) : array());
|
||||
}
|
||||
|
||||
public function getByStg()
|
||||
public function getCourses()
|
||||
{
|
||||
$this->_ci->form_validation->set_data($_POST);
|
||||
$this->_ci->form_validation->set_rules('studiengaenge[]',"studiengaenge","required");
|
||||
$this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
|
||||
|
||||
if($this->_ci->form_validation->run() === FALSE)
|
||||
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
|
||||
|
||||
$studiengaenge = $this->input->post('studiengaenge');
|
||||
$studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
|
||||
$studiensemester_kurzbz = $this->_ci->input->post('studiensemester_kurzbz', TRUE);
|
||||
|
||||
$filter = $this->_checkFilter(self::ALLOWED_COURSE_FILTER);
|
||||
|
||||
$this->_getBasePlan($studiensemester_kurzbz);
|
||||
|
||||
$this->_ci->LehreinheitModel->db->group_start();
|
||||
if (isset($filter->stg))
|
||||
$this->_addStgWhere($filter->stg);
|
||||
|
||||
if (isset($filter->uid))
|
||||
{
|
||||
$uid_array = (array) $filter->uid;
|
||||
$this->_ci->LehreinheitModel->db->or_where_in('tbl_benutzer.uid', $uid_array);
|
||||
}
|
||||
|
||||
$this->_ci->LehreinheitModel->db->group_end();
|
||||
|
||||
$this->_ci->LehreinheitModel->addOrder('lehreinheit_id');
|
||||
$result = $this->_ci->LehreinheitModel->load();
|
||||
$result = hasData($result) ? getData($result) : array();
|
||||
$this->terminateWithSuccess($this->_mapEvents($result));
|
||||
}
|
||||
|
||||
private function _getBasePlan($studiensemester_kurzbz)
|
||||
{
|
||||
$this->_ci->LehreinheitModel->addSelect('
|
||||
tbl_lehreinheit.lehreinheit_id,
|
||||
tbl_lehreinheit.lvnr,
|
||||
@@ -142,6 +96,15 @@ class Coursepicker extends FHCAPI_Controller
|
||||
$this->_ci->LehreinheitModel->addJoin('public.tbl_benutzer', 'ma.mitarbeiter_uid = tbl_benutzer.uid');
|
||||
$this->_ci->LehreinheitModel->addJoin('public.tbl_person', 'tbl_benutzer.person_id = tbl_person.person_id');
|
||||
|
||||
$this->_ci->LehreinheitModel->db->group_start();
|
||||
$this->_ci->LehreinheitModel->db->where('tbl_lehrform.verplanen', true);
|
||||
$this->_ci->LehreinheitModel->db->where('tbl_lehreinheit.studiensemester_kurzbz', $studiensemester_kurzbz);
|
||||
$this->_ci->LehreinheitModel->db->group_end();
|
||||
|
||||
}
|
||||
|
||||
private function _addStgWhere($studiengaenge)
|
||||
{
|
||||
$this->_ci->LehreinheitModel->db->group_start();
|
||||
$first = true;
|
||||
foreach ($studiengaenge as $studiengang)
|
||||
@@ -165,14 +128,10 @@ class Coursepicker extends FHCAPI_Controller
|
||||
$this->_ci->LehreinheitModel->db->group_end();
|
||||
}
|
||||
$this->_ci->LehreinheitModel->db->group_end();
|
||||
}
|
||||
|
||||
$result = $this->_ci->LehreinheitModel->loadWhere(array(
|
||||
'tbl_lehrform.verplanen' => true,
|
||||
'tbl_lehreinheit.studiensemester_kurzbz' => $studiensemester_kurzbz
|
||||
));
|
||||
|
||||
$result = hasData($result) ? getData($result) : array();
|
||||
|
||||
private function _mapEvents($result)
|
||||
{
|
||||
$lehreinheit_ids = array_values(array_unique(array_column($result, 'lehreinheit_id')));
|
||||
|
||||
$offen_map = array();
|
||||
@@ -281,10 +240,8 @@ class Coursepicker extends FHCAPI_Controller
|
||||
$group->verplant = $this->_formatArr($group->verplant);
|
||||
$group->offenestunden = $this->_formatArr($group->offenestunden);
|
||||
}
|
||||
|
||||
$this->terminateWithSuccess(array_values($grouped));
|
||||
return array_values($grouped);
|
||||
}
|
||||
|
||||
private function _formatArr($arr)
|
||||
{
|
||||
$values = array_values(array_unique($arr));
|
||||
@@ -296,5 +253,24 @@ class Coursepicker extends FHCAPI_Controller
|
||||
return $formatted;
|
||||
}
|
||||
|
||||
private function _checkFilter($filters)
|
||||
{
|
||||
$filter_valid = false;
|
||||
$filter_object = new stdClass();
|
||||
foreach ($filters as $filter)
|
||||
{
|
||||
if ($this->_ci->input->post($filter))
|
||||
{
|
||||
$filter_valid = true;
|
||||
$filter_object->$filter = $this->_ci->input->post($filter);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$filter_valid)
|
||||
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
return $filter_object;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ class Favorites extends FHCAPI_Controller
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'index' => self::PERM_LOGGED,
|
||||
'set' => self::PERM_LOGGED
|
||||
'index' => 'lehre/lvplan:rw',
|
||||
'set' => 'lehre/lvplan:rw'
|
||||
]);
|
||||
|
||||
// Load models
|
||||
|
||||
@@ -12,7 +12,7 @@ class Info extends FHCAPI_Controller
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getStudiengaenge' => self::PERM_LOGGED,
|
||||
'getStudiengaenge' => 'lehre/lvplan:rw',
|
||||
]);
|
||||
|
||||
$this->_ci =& get_instance();
|
||||
|
||||
@@ -8,18 +8,19 @@ class Kalender extends FHCAPI_Controller
|
||||
const ALLOWED_PLAN_FILTER = ['ort', 'uid', 'stg'];
|
||||
const ALLOWED_ROOM_FILTER = ['lehreinheit_id', 'kalender_id'];
|
||||
|
||||
const ALLOWED_TO_UPDATE = ['start_time', 'end_time', 'ort_kurzbz'];
|
||||
const ALLOWED_TO_UPDATE = ['start_time', 'end_time', 'orte'];
|
||||
/**
|
||||
* Object initialization
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getStunden' => self::PERM_LOGGED,
|
||||
'getCalendarHours' => self::PERM_LOGGED,
|
||||
'getPlan' => self::PERM_LOGGED,
|
||||
'getPlanByOrt' => self::PERM_LOGGED,
|
||||
'getRaumvorschlag' => self::PERM_LOGGED,
|
||||
'getStunden' => 'lehre/lvplan:rw',
|
||||
'getCalendarHours' => 'lehre/lvplan:rw',
|
||||
'getPlan' => 'lehre/lvplan:rw',
|
||||
'getPlanByOrt' => 'lehre/lvplan:rw',
|
||||
'getRaumvorschlag' => 'lehre/lvplan:rw',
|
||||
'getRaumvorschlagSlots' => 'lehre/lvplan:rw',
|
||||
'getLehreinheiten' => 'lehre/lvplan:rw',
|
||||
'getHistory' => 'lehre/lvplan:rw',
|
||||
'deleteEntry' => 'lehre/lvplan:rw',
|
||||
@@ -27,8 +28,8 @@ class Kalender extends FHCAPI_Controller
|
||||
'syncToStudent' => 'lehre/lvplan:rw',
|
||||
'getPlanLecturer' =>'lehre/lvplan:rw',
|
||||
'getPlanStudent' => 'lehre/lvplan:rw',
|
||||
'getZeitwuensche' => self::PERM_LOGGED,
|
||||
'getZeitsperren' => self::PERM_LOGGED,
|
||||
'getZeitwuensche' => 'lehre/lvplan:rw',
|
||||
'getZeitsperren' => 'lehre/lvplan:rw',
|
||||
'updateKalenderEvent' => 'lehre/lvplan:rw',
|
||||
'deleteOrtEntry' => 'lehre/lvplan:rw',
|
||||
'deleteFromKalenderEvent' => 'lehre/lvplan:rw',
|
||||
@@ -44,6 +45,7 @@ class Kalender extends FHCAPI_Controller
|
||||
$this->_ci->load->library('LogLib');
|
||||
$this->_ci->load->library('form_validation');
|
||||
$this->_ci->load->library('KalenderLib');
|
||||
$this->_ci->load->library('KalenderSyncLib');
|
||||
$this->_ci->load->library('RaumvorschlagLib');
|
||||
$this->loadPhrases([
|
||||
'ui'
|
||||
@@ -222,7 +224,7 @@ class Kalender extends FHCAPI_Controller
|
||||
$updateFields = $this->_checkUpdate($this->_ci->input->post('updatedInfos', TRUE));
|
||||
$kalender_id = $this->_ci->input->post('kalender_id', TRUE);
|
||||
|
||||
$result = $this->_ci->kalenderlib->updateKalenderEvent($kalender_id, $updateFields->ort_kurzbz ?? null, $updateFields->start_time ?? null, $updateFields->end_time ?? null);
|
||||
$result = $this->_ci->kalenderlib->updateKalenderEvent($kalender_id, $updateFields->orte ?? null, $updateFields->start_time ?? null, $updateFields->end_time ?? null, $updateFields->location ?? null);
|
||||
|
||||
if (isError($result))
|
||||
$this->terminateWithError(getError($result), $result->code);
|
||||
@@ -255,6 +257,22 @@ class Kalender extends FHCAPI_Controller
|
||||
$this->terminateWithSuccess($this->_ci->raumvorschlaglib->getVorschlaege($filter->kalender_id));
|
||||
}
|
||||
|
||||
public function getRaumvorschlagSlots()
|
||||
{
|
||||
$this->_ci->form_validation->set_data($_GET);
|
||||
$this->_ci->form_validation->set_rules('lehreinheit_id',"lehreinheit_id","required");
|
||||
$this->_ci->form_validation->set_rules('start_date',"start_date","required");
|
||||
$this->_ci->form_validation->set_rules('end_date',"end_date","required");
|
||||
|
||||
if($this->_ci->form_validation->run() === FALSE)
|
||||
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
|
||||
|
||||
$lehreinheit_id = $this->_ci->input->get('lehreinheit_id', TRUE);
|
||||
$start_date = $this->_ci->input->get('start_date', TRUE);
|
||||
$end_date = $this->_ci->input->get('end_date', TRUE);
|
||||
$this->terminateWithSuccess(getData($this->_ci->raumvorschlaglib->getVorschlaegeSlots($lehreinheit_id, $start_date, $end_date)));
|
||||
}
|
||||
|
||||
public function getLehreinheiten()
|
||||
{
|
||||
$this->_ci->form_validation->set_data($_GET);
|
||||
@@ -306,7 +324,7 @@ class Kalender extends FHCAPI_Controller
|
||||
|
||||
public function sync()
|
||||
{
|
||||
$result = $this->_ci->kalenderlib->sync();
|
||||
$result = $this->_ci->kalendersynclib->sync();
|
||||
$this->terminateWithSuccess(getData($result));
|
||||
}
|
||||
public function syncToLecturer()
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
if (!defined('BASEPATH'))
|
||||
exit('No direct script access allowed');
|
||||
|
||||
|
||||
class KalenderSync extends FHCAPI_Controller
|
||||
{
|
||||
private $_ci;
|
||||
|
||||
const ALLOWED_STATUS = ['preview', 'live'];
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getSyncs' => ['admin:r', 'assistenz:r'],
|
||||
'loadSync' => ['admin:r', 'assistenz:r'],
|
||||
'add' => ['admin:r', 'assistenz:r'],
|
||||
'start' => ['admin:r', 'assistenz:r'],
|
||||
'delete' => ['admin:r', 'assistenz:r'],
|
||||
'updateSync' => ['admin:r', 'assistenz:r'],
|
||||
'getStudienplan' => ['admin:r', 'assistenz:r'],
|
||||
'getSyncStatus' => ['admin:r', 'assistenz:r'],
|
||||
]);
|
||||
|
||||
$this->loadPhrases([
|
||||
'lehre',
|
||||
]);
|
||||
|
||||
$this->_ci = &get_instance();
|
||||
$this->_ci->load->library('form_validation');
|
||||
$this->_ci->load->model('organisation/Studienplan_model', 'StudienplanModel');
|
||||
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
|
||||
$this->_ci->load->model('ressource/Kalendersyncstatus_model', 'KalendersyncstatusModel');
|
||||
$this->_ci->load->model('ressource/Kalenderstatus_model', 'KalenderStatusModel');
|
||||
$this->_ci->load->library('KalenderSyncLib');
|
||||
}
|
||||
|
||||
public function getSyncs()
|
||||
{
|
||||
$this->_ci->form_validation->set_data($_GET);
|
||||
$this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
|
||||
|
||||
if($this->_ci->form_validation->run() === FALSE)
|
||||
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
|
||||
$studiensemester_kurzbz = $this->_ci->input->get('studiensemester_kurzbz', TRUE);
|
||||
|
||||
$language = getUserLanguage() == 'German' ? 0 : 1;
|
||||
|
||||
$this->_ci->KalenderStatusModel->addSelect('tbl_kalender_syncstatus.*, array_to_json(bezeichnung_mehrsprachig::varchar[])->>' . $language .' AS sync_status, tbl_organisationseinheit.bezeichnung as oebezeichnung, tbl_studienplan.bezeichnung as studienplanbezeichnung');
|
||||
$this->_ci->KalenderStatusModel->addJoin('lehre.tbl_kalender_status', 'tbl_kalender_syncstatus.sync_status_kurzbz = tbl_kalender_status.status_kurzbz');
|
||||
$this->_ci->KalenderStatusModel->addJoin('public.tbl_organisationseinheit', 'tbl_kalender_syncstatus.oe_kurzbz = tbl_organisationseinheit.oe_kurzbz');
|
||||
$this->_ci->KalenderStatusModel->addJoin('lehre.tbl_studienplan', 'tbl_kalender_syncstatus.studienplan_id = tbl_studienplan.studienplan_id', 'LEFT');
|
||||
$this->_ci->KalenderStatusModel->addJoin('public.tbl_studiensemester', 'tbl_kalender_syncstatus.studiensemester_kurzbz = tbl_studiensemester.studiensemester_kurzbz');
|
||||
$this->_ci->KalenderStatusModel->addOrder('public.tbl_studiensemester.start', 'DESC');
|
||||
|
||||
|
||||
if ($studiensemester_kurzbz === 'all')
|
||||
$data = $this->_ci->KalendersyncstatusModel->load();
|
||||
else
|
||||
$data = $this->_ci->KalendersyncstatusModel->loadWhere(array('tbl_kalender_syncstatus.studiensemester_kurzbz' => $studiensemester_kurzbz));
|
||||
|
||||
if (isError($data))
|
||||
$this->terminateWithError(getError($data));
|
||||
|
||||
$this->terminateWithSuccess(getData($data));
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('kalender_syncstatus_id', 'kalender_syncstatus_id', 'required');
|
||||
|
||||
if (!$this->form_validation->run())
|
||||
$this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
$kalender_syncstatus_id = $this->input->post('kalender_syncstatus_id');
|
||||
|
||||
$result = $this->_ci->KalendersyncstatusModel->load($kalender_syncstatus_id);
|
||||
|
||||
if (isError($result))
|
||||
$this->terminateWithError(getError($result));
|
||||
|
||||
if (!hasData($result))
|
||||
$this->terminateWithError($this->p->t('lehre', 'errorDeleting'));
|
||||
|
||||
$del_result = $this->_ci->KalendersyncstatusModel->delete(getData($result)[0]->kalender_syncstatus_id);
|
||||
|
||||
if (isError($del_result))
|
||||
$this->terminateWithError(getError($del_result));
|
||||
$this->terminateWithSuccess($del_result);
|
||||
}
|
||||
|
||||
public function loadSync()
|
||||
{
|
||||
$this->_ci->form_validation->set_data($_GET);
|
||||
$this->_ci->form_validation->set_rules('kalender_syncstatus_id',"kalender_syncstatus_id","required");
|
||||
|
||||
if($this->_ci->form_validation->run() === FALSE)
|
||||
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
|
||||
$kalender_syncstatus_id = $this->_ci->input->get('kalender_syncstatus_id', TRUE);
|
||||
$data = $this->_ci->KalendersyncstatusModel->loadWhere(array('kalender_syncstatus_id' => $kalender_syncstatus_id));
|
||||
if (isError($data))
|
||||
$this->terminateWithError(getError($data));
|
||||
|
||||
$this->terminateWithSuccess(getData($data)[0]);
|
||||
}
|
||||
|
||||
public function getSyncStatus()
|
||||
{
|
||||
$language = getUserLanguage() == 'German' ? 0 : 1;
|
||||
|
||||
$this->_ci->KalenderStatusModel->addSelect('*, array_to_json(bezeichnung_mehrsprachig::varchar[])->>' . $language .' AS bezeichnung, status_kurzbz');
|
||||
$this->_ci->KalenderStatusModel->db->where_in('status_kurzbz', self::ALLOWED_STATUS);
|
||||
$data = $this->_ci->KalenderStatusModel->load();
|
||||
|
||||
if (isError($data))
|
||||
$this->terminateWithError(getError($data));
|
||||
|
||||
$this->terminateWithSuccess(getData($data));
|
||||
}
|
||||
|
||||
|
||||
public function add()
|
||||
{
|
||||
$formData = $this->input->post('formData');
|
||||
|
||||
$this->_ci->form_validation->set_data($formData);
|
||||
|
||||
$this->_ci->form_validation->set_rules('oe_kurzbz',"oe_kurzbz","required");
|
||||
$this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
|
||||
$this->_ci->form_validation->set_rules('sync_status_kurzbz',"sync_status_kurzbz","required");
|
||||
|
||||
if($this->_ci->form_validation->run() === FALSE)
|
||||
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
|
||||
|
||||
$ausbildungssemester = isEmptyString($formData['ausbildungssemester']) ? null : $formData['ausbildungssemester'];
|
||||
$studienplan_id = isEmptyString($formData['studienplan_id']) ? null : $formData['studienplan_id'];
|
||||
|
||||
$existing = $this->_checkIfExist(
|
||||
$formData['oe_kurzbz'],
|
||||
$formData['studiensemester_kurzbz'],
|
||||
$ausbildungssemester,
|
||||
$studienplan_id
|
||||
);
|
||||
|
||||
if (isError($existing))
|
||||
$this->terminateWithError(getError($existing));
|
||||
|
||||
if (hasData($existing))
|
||||
{
|
||||
$this->terminateWithError('Es existiert bereits ein Eintrag.');
|
||||
}
|
||||
|
||||
$result = $this->_ci->KalendersyncstatusModel->insert(
|
||||
array(
|
||||
'oe_kurzbz' => $formData['oe_kurzbz'],
|
||||
'studiensemester_kurzbz' => $formData['studiensemester_kurzbz'],
|
||||
'datum_bis' => $formData['datum_bis'],
|
||||
'studienplan_id' => $studienplan_id,
|
||||
'ausbildungssemester' => $ausbildungssemester,
|
||||
'sync_status_kurzbz' => $formData['sync_status_kurzbz'],
|
||||
'mail' => $formData['mail'],
|
||||
'insertvon' => getAuthUID()
|
||||
)
|
||||
);
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
|
||||
|
||||
public function start()
|
||||
{
|
||||
$formData = $this->input->post('formData');
|
||||
|
||||
$this->_ci->form_validation->set_data($formData);
|
||||
|
||||
$this->_ci->form_validation->set_rules('oe_kurzbz',"oe_kurzbz","required");
|
||||
$this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
|
||||
$this->_ci->form_validation->set_rules('sync_status_kurzbz',"sync_status_kurzbz","required");
|
||||
|
||||
if($this->_ci->form_validation->run() === FALSE)
|
||||
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
|
||||
|
||||
$result = $this->_ci->kalendersynclib->runManual($formData['oe_kurzbz'], $formData['studiensemester_kurzbz'], $formData['ausbildungssemester'], $formData['studienplan_id'], $formData['mail'], $formData['datum_bis'], $formData['sync_status_kurzbz']);
|
||||
|
||||
if (isError($result))
|
||||
$this->terminateWithError(getError($result));
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
public function updateSync()
|
||||
{
|
||||
$formData = $this->input->post('formData');
|
||||
|
||||
$this->_ci->form_validation->set_data($formData);
|
||||
|
||||
$this->_ci->form_validation->set_rules('kalender_syncstatus_id',"kalender_syncstatus_id","required");
|
||||
$this->_ci->form_validation->set_rules('oe_kurzbz',"oe_kurzbz","required");
|
||||
$this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
|
||||
$this->_ci->form_validation->set_rules('sync_status_kurzbz',"sync_status_kurzbz","required");
|
||||
|
||||
if($this->_ci->form_validation->run() === FALSE)
|
||||
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
|
||||
|
||||
$ausbildungssemester = isEmptyString($formData['ausbildungssemester']) ? null : $formData['ausbildungssemester'];
|
||||
$studienplan_id = isEmptyString($formData['studienplan_id']) ? null : $formData['studienplan_id'];
|
||||
|
||||
$existing = $this->_checkIfExist(
|
||||
$formData['oe_kurzbz'],
|
||||
$formData['studiensemester_kurzbz'],
|
||||
$ausbildungssemester,
|
||||
$studienplan_id,
|
||||
$formData['kalender_syncstatus_id']
|
||||
);
|
||||
|
||||
if (isError($existing))
|
||||
$this->terminateWithError(getError($existing));
|
||||
|
||||
if (hasData($existing))
|
||||
{
|
||||
$this->terminateWithError('Es existiert bereits ein Eintrag.');
|
||||
}
|
||||
|
||||
$this->_ci->KalendersyncstatusModel->update(
|
||||
array('kalender_syncstatus_id' => $formData['kalender_syncstatus_id']),
|
||||
array(
|
||||
'oe_kurzbz' => $formData['oe_kurzbz'],
|
||||
'studiensemester_kurzbz' => $formData['studiensemester_kurzbz'],
|
||||
'datum_bis' => $formData['datum_bis'],
|
||||
'studienplan_id' => $studienplan_id,
|
||||
'ausbildungssemester' => $ausbildungssemester,
|
||||
'sync_status_kurzbz' => $formData['sync_status_kurzbz'],
|
||||
'mail' => $formData['mail'],
|
||||
'updatevon' => getAuthUID(),
|
||||
'updateamum' => date('c'),
|
||||
)
|
||||
);
|
||||
}
|
||||
public function getStudienplan()
|
||||
{
|
||||
$this->_ci->form_validation->set_data($_GET);
|
||||
$this->_ci->form_validation->set_rules('oe_kurzbz',"oe_kurzbz","required");
|
||||
|
||||
if($this->_ci->form_validation->run() === FALSE)
|
||||
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
|
||||
|
||||
$oe_kurzbz = $this->_ci->input->get('oe_kurzbz', TRUE);
|
||||
$studiensemester_kurzbz = $this->_ci->input->get('studiensemester_kurzbz', TRUE);
|
||||
$ausbildungssemester = $this->_ci->input->get('ausbildungssemester', TRUE);
|
||||
|
||||
$this->_ci->StudiengangModel->addJoin('tbl_organisationseinheit', 'oe_kurzbz');
|
||||
$is_studiengang = $this->_ci->StudiengangModel->loadWhere(array('oe_kurzbz' => $oe_kurzbz));
|
||||
|
||||
if (hasData($is_studiengang) && !isEmptyString($studiensemester_kurzbz))
|
||||
{
|
||||
$studiengang = getData($is_studiengang)[0];
|
||||
|
||||
$studienplaene = $this->_ci->StudienplanModel->getStudienplaeneBySemester(
|
||||
$studiengang->studiengang_kz,
|
||||
$studiensemester_kurzbz,
|
||||
isEmptyString($ausbildungssemester) ? null : $ausbildungssemester
|
||||
);
|
||||
|
||||
|
||||
$data = $this->getDataOrTerminateWithError($studienplaene);
|
||||
|
||||
$unique = array();
|
||||
foreach ($data as $row)
|
||||
{
|
||||
$unique[$row->studienplan_id] = (object) array(
|
||||
'studienplan_id' => $row->studienplan_id,
|
||||
'studienordnung_id' => $row->studienordnung_id,
|
||||
'bezeichnung' => $row->bezeichnung,
|
||||
'orgform_kurzbz' => $row->orgform_kurzbz
|
||||
);
|
||||
}
|
||||
|
||||
$this->terminateWithSuccess(array_values($unique));
|
||||
}
|
||||
$this->terminateWithSuccess();
|
||||
}
|
||||
|
||||
private function _checkIfExist($oe_kurzbz, $studiensemester_kurzbz, $ausbildungssemester, $studienplan_id, $kalender_syncstatus_id = null)
|
||||
{
|
||||
$this->_ci->KalendersyncstatusModel->db->where('oe_kurzbz', $oe_kurzbz);
|
||||
$this->_ci->KalendersyncstatusModel->db->where('studiensemester_kurzbz', $studiensemester_kurzbz);
|
||||
|
||||
if (is_null($ausbildungssemester))
|
||||
$this->_ci->KalendersyncstatusModel->db->where('ausbildungssemester IS NULL', null, false);
|
||||
else
|
||||
$this->_ci->KalendersyncstatusModel->db->where('ausbildungssemester', $ausbildungssemester);
|
||||
|
||||
if (is_null($studienplan_id))
|
||||
$this->_ci->KalendersyncstatusModel->db->where('studienplan_id IS NULL', null, false);
|
||||
else
|
||||
$this->_ci->KalendersyncstatusModel->db->where('studienplan_id', $studienplan_id);
|
||||
|
||||
if (!is_null($kalender_syncstatus_id))
|
||||
$this->_ci->KalendersyncstatusModel->db->where('kalender_syncstatus_id !=', $kalender_syncstatus_id);
|
||||
return $this->_ci->KalendersyncstatusModel->load();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,9 +9,9 @@ class OperationalResourceToCalenderAPI extends FHCAPI_Controller
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getAssignedResourcesByCalender' => ['admin:r', 'assistenz:r'],
|
||||
'storeResourcesToCalendarRelationship' => ['admin:w', 'assistenz:w'],
|
||||
'getSchedulableResourcesByCalendar' => ['admin:r', 'assistenz:r'],
|
||||
'getAssignedResourcesByCalender' => ['admin:r', 'assistenz:r', 'lehre/lvplan:rw'],
|
||||
'storeResourcesToCalendarRelationship' => ['admin:w', 'assistenz:w', 'lehre/lvplan:rw'],
|
||||
'getSchedulableResourcesByCalendar' => ['admin:r', 'assistenz:r', 'lehre/lvplan:rw'],
|
||||
]);
|
||||
|
||||
$this->load->model('ressource/BetriebsmittelKalender_model', 'BetriebsmittelKalenderModel');
|
||||
|
||||
@@ -162,9 +162,9 @@ class Reservierung extends FHCAPI_Controller
|
||||
if ($this->_ci->form_validation->run() === FALSE)
|
||||
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
|
||||
|
||||
$ort_kurzbz = $this->_ci->input->post('ort_kurzbz', TRUE);
|
||||
$orte = $this->_ci->input->post('orte', TRUE);
|
||||
|
||||
if (empty($ort_kurzbz) || !is_array($ort_kurzbz))
|
||||
if (empty($orte) || (empty($orte['ort_kurzbz']) && empty($orte['location'])))
|
||||
{
|
||||
$this->terminateWithValidationErrors(['ort_kurzbz' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Raum'])]);
|
||||
}
|
||||
@@ -189,7 +189,7 @@ class Reservierung extends FHCAPI_Controller
|
||||
$teilnehmer[] = array('uid' => getAuthUID(), 'rolle' => 'organisator');
|
||||
|
||||
|
||||
$result = $this->_ci->kalenderlib->addReservierung($titel, $beschreibung, $ort_kurzbz, $start_date, $end_date, $teilnehmer, $specialFinalGroups, $specialGroups, $groups);
|
||||
$result = $this->_ci->kalenderlib->addReservierung($titel, $beschreibung, $orte, $start_date, $end_date, $teilnehmer, $specialFinalGroups, $specialGroups, $groups);
|
||||
|
||||
|
||||
if (isError($result))
|
||||
|
||||
@@ -121,7 +121,14 @@ class MigrateKalender extends CLI_Controller
|
||||
$ids = is_array($block->stundenplandev_ids) ? $block->stundenplandev_ids : explode(',', $block->stundenplandev_ids);
|
||||
/*$ids = array_map('intval', $ids);*/
|
||||
|
||||
$this->SyncModel->db->where_in('stundenplandev_id', $ids);
|
||||
$this->SyncModel->db->group_start();
|
||||
$where_ids_chunks = array_chunk($ids,25);
|
||||
foreach($where_ids_chunks as $where_ids)
|
||||
{
|
||||
$this->SyncModel->db->or_where_in('stundenplandev_id', $where_ids);
|
||||
}
|
||||
$this->SyncModel->db->group_end();
|
||||
|
||||
$sync_result = $this->SyncModel->load();
|
||||
|
||||
if (!hasData($sync_result))
|
||||
@@ -230,7 +237,14 @@ class MigrateKalender extends CLI_Controller
|
||||
|
||||
$ids = is_array($block->reservierung_ids) ? $block->reservierung_ids : explode(',', $block->reservierung_ids);
|
||||
|
||||
$this->SyncReservierungModel->db->where_in('reservierung_id', $ids);
|
||||
$this->SyncReservierungModel->db->group_start();
|
||||
$where_ids_chunks = array_chunk($ids,25);
|
||||
foreach($where_ids_chunks as $where_ids)
|
||||
{
|
||||
$this->SyncReservierungModel->db->or_where_in('reservierung_id', $where_ids);
|
||||
}
|
||||
$this->SyncReservierungModel->db->group_end();
|
||||
|
||||
$sync_result = $this->SyncReservierungModel->load();
|
||||
|
||||
if (!hasData($sync_result))
|
||||
|
||||
@@ -17,7 +17,6 @@ class KalenderLib
|
||||
$this->_ci->load->model('ressource/BetriebsmittelKalender_model', 'BetriebsmittelKalenderModel');
|
||||
$this->_ci->load->model('education/Lehreinheit_model', 'LehreinheitModel');
|
||||
$this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
|
||||
$this->_ci->load->model('education/LehreinheitMitarbeiter_model', 'LehreinheitMitarbeiterModel');
|
||||
$this->_ci->load->model('ressource/Ort_model', 'OrtModel');
|
||||
$this->_ci->load->model('organisation/gruppe_model', 'GruppeModel');
|
||||
$this->_ci->load->model('organisation/Lehrverband_model', 'LehrverbandModel');
|
||||
@@ -48,6 +47,7 @@ class KalenderLib
|
||||
tbl_kalender.typ,
|
||||
tbl_kalender.von,
|
||||
tbl_kalender.bis,
|
||||
tbl_kalender_ort.location,
|
||||
tbl_kalender_ort.ort_kurzbz,
|
||||
tbl_lehreinheit.lehreinheit_id,
|
||||
tbl_lehreinheit.lehrveranstaltung_id,
|
||||
@@ -91,7 +91,19 @@ class KalenderLib
|
||||
tbl_lehreinheitgruppe.gruppe as le_gruppe,
|
||||
le_gruppe.direktinskription as le_direktinskription,
|
||||
tag_data_agg.tags as tags,
|
||||
resource_data_agg.resources as resources
|
||||
resource_data_agg.resources as resources,
|
||||
CASE
|
||||
WHEN vonstunde.stunde IS NOT NULL AND bisstunde.stunde IS NOT NULL
|
||||
THEN bisstunde.stunde - vonstunde.stunde + 1
|
||||
ELSE ROUND(
|
||||
COALESCE(
|
||||
(
|
||||
SELECT SUM(EXTRACT(EPOCH FROM (LEAST(stunde.ende, tbl_kalender.bis::time) - GREATEST(stunde.beginn, tbl_kalender.von::time))) / 60) / 45
|
||||
FROM lehre.tbl_stunde stunde
|
||||
WHERE stunde.beginn < tbl_kalender.bis::time AND stunde.ende > tbl_kalender.von::time)
|
||||
,0)
|
||||
,2
|
||||
) END AS verplante_stunden
|
||||
');
|
||||
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit', 'tbl_kalender.kalender_id = tbl_kalender_lehreinheit.kalender_id', 'LEFT');
|
||||
@@ -201,6 +213,9 @@ class KalenderLib
|
||||
// End of operational resources inclusion
|
||||
|
||||
|
||||
$this->_ci->KalenderModel->db->join('lehre.tbl_stunde vonstunde', 'tbl_kalender.von::time = vonstunde.beginn', 'LEFT', FALSE);
|
||||
$this->_ci->KalenderModel->db->join('lehre.tbl_stunde bisstunde', 'tbl_kalender.bis::time = bisstunde.ende', 'LEFT', FALSE);
|
||||
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.von >=', $start_date);
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.bis <', $end_date);
|
||||
|
||||
@@ -238,11 +253,13 @@ class KalenderLib
|
||||
'tooltip' => 'tip',
|
||||
'status_kurzbz' => $row->status_kurzbz,
|
||||
'ort_kurzbz' => [],
|
||||
'location' => null,
|
||||
'lehrform' => isset($row->lehrform_kurzbz) ? $row->lehrform_kurzbz : '',
|
||||
'lehrfach' => isset($row->lehrfach_kurzbz) ? $row->lehrfach_kurzbz : '',
|
||||
'lehrfach_bez' => isset($row->lehrfach_bezeichnung) ? $row->lehrfach_bezeichnung : '',
|
||||
'farbe' => isset($row->farbe) ? $row->farbe : '',
|
||||
'lehrveranstaltung_id' => $row->lehrveranstaltung_id,
|
||||
'verplante_stunden' => $row->verplante_stunden,
|
||||
'organisationseinheit' => isset($row->oe_kurzbz) ? $row->oe_kurzbz : '',
|
||||
'kalender_id' => $id,
|
||||
'lehreinheit_id' => [],
|
||||
@@ -266,6 +283,9 @@ class KalenderLib
|
||||
if (isset($row->ort_kurzbz) && $row->ort_kurzbz !== '' && !in_array($row->ort_kurzbz, $events[$id]->ort_kurzbz))
|
||||
$events[$id]->ort_kurzbz[] = $row->ort_kurzbz;
|
||||
|
||||
if (isset($row->location) && $row->location !== '' && is_null($events[$id]->location))
|
||||
$events[$id]->location = $row->location;
|
||||
|
||||
$topic = trim((isset($row->lehrfach_kurzbz) ? $row->lehrfach_kurzbz : '').' '.(isset($row->lehrform_kurzbz) ? $row->lehrform_kurzbz : ''));
|
||||
if ($topic !== '' && !in_array($topic, $events[$id]->topic))
|
||||
$events[$id]->topic[] = $topic;
|
||||
@@ -357,8 +377,6 @@ class KalenderLib
|
||||
return $this->_mapEvents($data);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function getForRaumvorschlag($start_date, $end_date, $lektor_uids = [], $gruppen_kurzbz = [], $lehrverband_gruppen = [])
|
||||
{
|
||||
$start_date = date('Y-m-d', strtotime($start_date));
|
||||
@@ -384,6 +402,7 @@ class KalenderLib
|
||||
|
||||
foreach ($lehrverband_gruppen as $lvg)
|
||||
{
|
||||
$lvg = (array) $lvg;
|
||||
$this->_ci->KalenderModel->db->or_group_start();
|
||||
$this->_ci->KalenderModel->db->where('tbl_lehreinheitgruppe.studiengang_kz', $lvg['studiengang_kz']);
|
||||
$this->_ci->KalenderModel->db->where('tbl_lehreinheitgruppe.semester', $lvg['semester']);
|
||||
@@ -530,7 +549,7 @@ class KalenderLib
|
||||
{
|
||||
$this->_getBasePlan($start_date, $end_date);
|
||||
|
||||
$this->_ci->KalenderModel->db->where('status_kurzbz', 'live');
|
||||
$this->_ci->KalenderModel->db->where_in('status_kurzbz', array('live', 'to_delete_live'));
|
||||
|
||||
$data = $this->_ci->KalenderModel->load();
|
||||
|
||||
@@ -662,6 +681,17 @@ class KalenderLib
|
||||
|
||||
}
|
||||
|
||||
private function _checkCollisionForLehreinheit($start_date, $end_date, $lehreinheit_id, $ort_kurzbz)
|
||||
{
|
||||
$checkerData = new stdClass();
|
||||
$checkerData->von = $start_date;
|
||||
$checkerData->bis = $end_date;
|
||||
$checkerData->lehreinheit_id = $lehreinheit_id;
|
||||
$checkerData->ort_kurzbz = $ort_kurzbz;
|
||||
|
||||
return $this->_ci->collisionchecker->run($checkerData);
|
||||
}
|
||||
|
||||
public function addToKalenderEvent($target_kalender_id, $lehreinheit_id)
|
||||
{
|
||||
$entryResult = $this->_loadKalenderEntry($target_kalender_id);
|
||||
@@ -669,7 +699,15 @@ class KalenderLib
|
||||
|
||||
$kalender_entry = getData($entryResult);
|
||||
|
||||
if (in_array($kalender_entry->status_kurzbz, array('todelete', 'deleted')))
|
||||
if (!$this->_checkPermission($kalender_entry->lehreinheit_id))
|
||||
{
|
||||
return error([
|
||||
'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
|
||||
'errorCode' => 'not_allowed'
|
||||
]);
|
||||
}
|
||||
|
||||
if (in_array($kalender_entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview', 'deleted')))
|
||||
{
|
||||
return error([
|
||||
'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
|
||||
@@ -712,7 +750,15 @@ class KalenderLib
|
||||
|
||||
$kalender_entry = getData($entryResult);
|
||||
|
||||
if (in_array($kalender_entry->status_kurzbz, array('todelete', 'deleted')))
|
||||
if (!$this->_checkPermission($kalender_entry->lehreinheit_id))
|
||||
{
|
||||
return error([
|
||||
'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
|
||||
'errorCode' => 'not_allowed'
|
||||
]);
|
||||
}
|
||||
|
||||
if (in_array($kalender_entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview', 'deleted')))
|
||||
{
|
||||
return error([
|
||||
'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
|
||||
@@ -804,16 +850,6 @@ class KalenderLib
|
||||
return ['kalender_id' => $kalender_id, 'result' => $ortresult];
|
||||
}
|
||||
|
||||
$entryResult = $this->_loadKalenderEntry($kalender_id);
|
||||
if (isError($entryResult))
|
||||
return ['kalender_id' => $kalender_id, 'result' => $entryResult];
|
||||
|
||||
$kalender_entry = getData($entryResult);
|
||||
$errors = $this->_ci->collisionchecker->run($kalender_entry);
|
||||
|
||||
if (!empty($errors))
|
||||
return ['kalender_id' => $kalender_id, 'result' => error($errors)];
|
||||
|
||||
return ['kalender_id' => $kalender_id, 'result' => $kalenderlehreinheitresult];
|
||||
}
|
||||
|
||||
@@ -878,8 +914,6 @@ class KalenderLib
|
||||
'false'
|
||||
);
|
||||
|
||||
$this->_ci->KalenderModel->db->trans_start();
|
||||
|
||||
while ($rest > 0 && new DateTime($current_date) < $ende)
|
||||
{
|
||||
$max_skip = 52;
|
||||
@@ -920,18 +954,9 @@ class KalenderLib
|
||||
$start_str = $current_date . ' ' . $start_time;
|
||||
$end_str = $current_date . ' ' . $end_time;
|
||||
|
||||
$insert = $this->_insertKalenderEventRaw($start_str, $end_str, $lehreinheit_id, $ort_kurzbz);
|
||||
$kalender_id = $insert['kalender_id'];
|
||||
$insert_result = $insert['result'];
|
||||
$collisions = $this->_checkCollisionForLehreinheit($start_str, $end_str, $lehreinheit_id, $ort_kurzbz);
|
||||
|
||||
$collisions = isError($insert_result) ? getError($insert_result) : [];
|
||||
|
||||
$raum_vorschlaege = [];
|
||||
if ($kalender_id)
|
||||
{
|
||||
$vorschlaege = $this->_ci->raumvorschlaglib->getVorschlaege($kalender_id);
|
||||
$raum_vorschlaege = is_array($vorschlaege) ? $vorschlaege : [];
|
||||
}
|
||||
$raum_vorschlaege = $this->_ci->raumvorschlaglib->getVorschlaegeByLehreinheit($lehreinheit_id, $start_str, $end_str);
|
||||
|
||||
$plan[] = [
|
||||
'datum' => $current_date,
|
||||
@@ -940,14 +965,13 @@ class KalenderLib
|
||||
'block' => $current_block,
|
||||
'ort_kurzbz' => $ort_kurzbz,
|
||||
'collisions' => $collisions,
|
||||
'raum_vorschlaege' => $raum_vorschlaege,
|
||||
'raum_vorschlaege' => is_array($raum_vorschlaege) ? $raum_vorschlaege : [],
|
||||
];
|
||||
|
||||
$rest -= $current_block;
|
||||
$current_date = $this->_addWeeks($current_date, $wochenrythmus);
|
||||
}
|
||||
|
||||
$this->_ci->KalenderModel->db->trans_rollback();
|
||||
|
||||
$this->_ci->VariableModel->setVariable(
|
||||
getAuthUID(),
|
||||
@@ -1010,6 +1034,49 @@ class KalenderLib
|
||||
|
||||
public function addKalenderEvent($start_date, $end_date, $lehreinheit_id, $ort_kurzbz)
|
||||
{
|
||||
if (!$this->_checkPermission((array)$lehreinheit_id))
|
||||
{
|
||||
return error([
|
||||
'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
|
||||
'errorCode' => 'not_allowed'
|
||||
]);
|
||||
}
|
||||
|
||||
if (isEmptyString($ort_kurzbz))
|
||||
{
|
||||
$errors = $this->_checkCollisionForLehreinheit($start_date, $end_date, $lehreinheit_id, $ort_kurzbz);
|
||||
|
||||
if (!empty($errors))
|
||||
return error($errors);
|
||||
|
||||
$raum_vorschlaege = $this->_ci->raumvorschlaglib->getVorschlaegeByLehreinheit($lehreinheit_id, $start_date, $end_date);
|
||||
|
||||
if (($this->_ci->variablelib->getVar('dialog_room_planning') ?? 'false') === 'true')
|
||||
{
|
||||
return success([
|
||||
'needs_room_selection' => true,
|
||||
'raum_vorschlaege' => is_array($raum_vorschlaege) ? $raum_vorschlaege : [],
|
||||
]);
|
||||
}
|
||||
|
||||
if (($this->_ci->variablelib->getVar('priority_room_planning') ?? 'false') === 'true')
|
||||
{
|
||||
$ort_kurzbz = (is_array($raum_vorschlaege)) ? $raum_vorschlaege[0]['ort_kurzbz'] : null;
|
||||
}
|
||||
else if (!(($this->_ci->variablelib->getVar('roomless_planning') ?? 'false') === 'true'))
|
||||
{
|
||||
return error([
|
||||
'message' => $this->_ci->phraseslib->t('ui', 'roomless_planning_error'),
|
||||
'errorCode' => 'roomless_planning_error'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
$errors = $this->_checkCollisionForLehreinheit($start_date, $end_date, $lehreinheit_id, $ort_kurzbz);
|
||||
|
||||
if (!empty($errors))
|
||||
return error($errors);
|
||||
|
||||
$this->_ci->KalenderModel->db->trans_start();
|
||||
|
||||
$insert = $this->_insertKalenderEventRaw($start_date, $end_date, $lehreinheit_id, $ort_kurzbz);
|
||||
@@ -1025,14 +1092,14 @@ class KalenderLib
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function addReservierung($titel, $beschreibung, $ort_kurzbz, $start_date, $end_date, $teilnehmer, $specialFinalGroups, $specialGroups, $groups)
|
||||
public function addReservierung($titel, $beschreibung, $orte, $start_date, $end_date, $teilnehmer, $specialFinalGroups, $specialGroups, $groups)
|
||||
{
|
||||
|
||||
if (!is_null($ort_kurzbz))
|
||||
if (!is_null($orte) && !isEmptyArray($orte['ort_kurzbz']))
|
||||
{
|
||||
$this->_ci->KalenderModel->addSelect('1');
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'kalender_id');
|
||||
$this->_ci->KalenderModel->db->where_in('ort_kurzbz', $ort_kurzbz);
|
||||
$this->_ci->KalenderModel->db->where_in('ort_kurzbz', $orte['ort_kurzbz']);
|
||||
$reservierung_vorhanden = $this->_ci->KalenderModel->load(array (
|
||||
'von <=' => $end_date,
|
||||
'bis >=' => $start_date,
|
||||
@@ -1093,9 +1160,25 @@ class KalenderLib
|
||||
}
|
||||
}
|
||||
|
||||
if (isSuccess($kalendereventresult) && !is_null($ort_kurzbz))
|
||||
if (isSuccess($kalendereventresult) && !isEmptyArray($orte['ort_kurzbz']))
|
||||
{
|
||||
$ortresult = $this->_addKalenderOrt($kalender_id, $ort_kurzbz);
|
||||
$ortresult = $this->_addKalenderOrt($kalender_id, $orte['ort_kurzbz']);
|
||||
if (isError($ortresult))
|
||||
{
|
||||
$this->_ci->KalenderModel->db->trans_rollback();
|
||||
return $ortresult;
|
||||
}
|
||||
}
|
||||
|
||||
if (isSuccess($kalendereventresult) && !is_null($orte['location']))
|
||||
{
|
||||
$ortresult = $this->_ci->KalenderOrtModel->insert(
|
||||
array (
|
||||
'kalender_id' => $kalender_id,
|
||||
'location' => $orte['location']
|
||||
)
|
||||
);
|
||||
|
||||
if (isError($ortresult))
|
||||
{
|
||||
$this->_ci->KalenderModel->db->trans_rollback();
|
||||
@@ -1295,26 +1378,39 @@ class KalenderLib
|
||||
return success();
|
||||
}
|
||||
|
||||
public function updateKalenderEvent($kalender_id, $ort_kurzbz = null, $start_time = null, $end_time = null)
|
||||
public function updateKalenderEvent($kalender_id, $orte = null, $start_time = null, $end_time = null)
|
||||
{
|
||||
$entryResult = $this->_loadKalenderEntry($kalender_id);
|
||||
if (isError($entryResult)) return $entryResult;
|
||||
|
||||
$kalender_entry = getData($entryResult);
|
||||
|
||||
if (!$this->_checkPermission($kalender_entry->lehreinheit_id))
|
||||
{
|
||||
return error([
|
||||
'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
|
||||
'errorCode' => 'not_allowed'
|
||||
]);
|
||||
}
|
||||
|
||||
$calendarResources = $this->_ci->BetriebsmittelKalenderModel->loadWhere(['eindeutige_kalender_gruppen_id' => $kalender_entry->eindeutige_kalender_gruppen_id]);
|
||||
if (isError($calendarResources)) return $calendarResources;
|
||||
|
||||
|
||||
$calendarResourcesItems = getData($calendarResources);
|
||||
$calendarResourcesIDs = [];
|
||||
if (is_array($calendarResourcesItems)) {
|
||||
if (is_array($calendarResourcesItems)) {
|
||||
$calendarResourcesIDs = array_map(function($resource) {
|
||||
return $resource->betriebsmittel_id;
|
||||
}, getData($calendarResources));
|
||||
}
|
||||
}
|
||||
|
||||
$kalender_entry->betriebsmittel_ids = $calendarResourcesIDs;
|
||||
$kalender_entry->ort_kurzbz = !is_null($ort_kurzbz) ? (array) $ort_kurzbz : $kalender_entry->ort_kurzbz;
|
||||
|
||||
if (!is_null($orte))
|
||||
{
|
||||
$kalender_entry->ort_kurbz = !isEmptyArray($orte['ort_kurzbz'] ?? null) ? (array) $orte['ort_kurzbz'] : $kalender_entry->ort_kurzbz;
|
||||
$kalender_entry->location = array_key_exists('location', $orte) && !is_null($orte['location']) ? $orte['location'] : $kalender_entry->location;
|
||||
}
|
||||
$kalender_entry->von = $start_time ?? $kalender_entry->von;
|
||||
$kalender_entry->bis = $end_time ?? $kalender_entry->bis;
|
||||
|
||||
@@ -1324,9 +1420,9 @@ class KalenderLib
|
||||
|
||||
$result = $kalender_entry;
|
||||
|
||||
if (!is_null($ort_kurzbz))
|
||||
if (!is_null($orte))
|
||||
{
|
||||
$result = $this->updateOrt($kalender_id, $ort_kurzbz);
|
||||
$result = $this->updateOrt($kalender_id, $orte);
|
||||
if (isError($result)) return $result;
|
||||
|
||||
if (hasData($result))
|
||||
@@ -1353,7 +1449,7 @@ class KalenderLib
|
||||
|
||||
if ($kalender_entry->typ === 'lehreinheit')
|
||||
{
|
||||
if (in_array($kalender_entry->status_kurzbz, array('todelete', 'deleted')))
|
||||
if (in_array($kalender_entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview', 'deleted')))
|
||||
{
|
||||
return error([
|
||||
'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
|
||||
@@ -1409,9 +1505,11 @@ class KalenderLib
|
||||
return success($result);
|
||||
}
|
||||
|
||||
public function updateOrt($kalender_id, $ort_kurzbz_array)
|
||||
public function updateOrt($kalender_id, $orte_array)
|
||||
{
|
||||
$ort_kurzbz_array = (array)$ort_kurzbz_array;
|
||||
$ort_kurzbz_neu = (array)($orte_array['ort_kurzbz'] ?? []);
|
||||
$location_neu = $orte_array['location'] ?? null;
|
||||
|
||||
$entryResult = $this->_loadKalenderEntry($kalender_id);
|
||||
if (isError($entryResult)) return $entryResult;
|
||||
|
||||
@@ -1419,7 +1517,15 @@ class KalenderLib
|
||||
|
||||
if ($kalender_entry->typ === 'lehreinheit')
|
||||
{
|
||||
if (in_array($kalender_entry->status_kurzbz, array('todelete', 'deleted')))
|
||||
if (!$this->_checkPermission($kalender_entry->lehreinheit_id))
|
||||
{
|
||||
return error([
|
||||
'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
|
||||
'errorCode' => 'not_allowed'
|
||||
]);
|
||||
}
|
||||
|
||||
if (in_array($kalender_entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview', 'deleted')))
|
||||
{
|
||||
return error([
|
||||
'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
|
||||
@@ -1428,14 +1534,30 @@ class KalenderLib
|
||||
}
|
||||
|
||||
if (in_array($kalender_entry->status_kurzbz, array('live', 'preview')))
|
||||
return $this->_createHistoryEntry($kalender_entry, null, null, $ort_kurzbz_array);
|
||||
return $this->_createHistoryEntry($kalender_entry, null, null, $orte_array);
|
||||
}
|
||||
|
||||
$bestehende = $this->_ci->KalenderOrtModel->load(array('kalender_id' => $kalender_id));
|
||||
$alte_orte = hasData($bestehende) ? array_column(getData($bestehende), 'ort_kurzbz') : [];
|
||||
$alte_orte = hasData($bestehende) ? getData($bestehende) : [];
|
||||
|
||||
$zu_loeschen = array_diff($alte_orte, $ort_kurzbz_array);
|
||||
$neu_anzulegen = array_diff($ort_kurzbz_array, $alte_orte);
|
||||
|
||||
$alte_orte_kurzbz = array_values(array_filter(array_map(function ($ort) {
|
||||
return $ort->ort_kurzbz;
|
||||
}, $alte_orte)));
|
||||
|
||||
$alte_location = null;
|
||||
|
||||
foreach ($alte_orte as $ort)
|
||||
{
|
||||
if (!is_null($ort->location))
|
||||
{
|
||||
$alte_location = $ort->location;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$zu_loeschen = array_diff($alte_orte_kurzbz, $ort_kurzbz_neu);
|
||||
$neu_anzulegen = array_diff($ort_kurzbz_neu, $alte_orte_kurzbz);
|
||||
|
||||
if (!empty($zu_loeschen))
|
||||
{
|
||||
@@ -1444,12 +1566,34 @@ class KalenderLib
|
||||
$this->_ci->KalenderOrtModel->db->delete('lehre.tbl_kalender_ort');
|
||||
}
|
||||
|
||||
foreach ($neu_anzulegen as $ort_kurzbz)
|
||||
foreach ($neu_anzulegen as $ort)
|
||||
{
|
||||
$result = $this->_addKalenderOrt($kalender_id, $ort_kurzbz);
|
||||
$result = $this->_addKalenderOrt($kalender_id, $ort);
|
||||
if (isError($result)) return $result;
|
||||
}
|
||||
|
||||
if ($alte_location !== $location_neu)
|
||||
{
|
||||
if (!is_null($alte_location))
|
||||
{
|
||||
$this->_ci->KalenderOrtModel->db->where('kalender_id', $kalender_id);
|
||||
$this->_ci->KalenderOrtModel->db->where('ort_kurzbz IS NULL', null, false);
|
||||
$this->_ci->KalenderOrtModel->db->delete('lehre.tbl_kalender_ort');
|
||||
}
|
||||
|
||||
if (!isEmptyString($location_neu))
|
||||
{
|
||||
$ortresult = $this->_ci->KalenderOrtModel->insert(
|
||||
array (
|
||||
'kalender_id' => $kalender_id,
|
||||
'location' => $location_neu
|
||||
)
|
||||
);
|
||||
|
||||
if (isError($ortresult)) return $ortresult;
|
||||
}
|
||||
}
|
||||
|
||||
return success();
|
||||
}
|
||||
|
||||
@@ -1460,6 +1604,14 @@ class KalenderLib
|
||||
|
||||
$kalender_entry = getData($entryResult);
|
||||
|
||||
if (!$this->_checkPermission($kalender_entry->lehreinheit_id))
|
||||
{
|
||||
return error([
|
||||
'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
|
||||
'errorCode' => 'not_allowed'
|
||||
]);
|
||||
}
|
||||
|
||||
$allowed = array(
|
||||
'planning' => array('sync_preview', 'sync_live'),
|
||||
'sync_preview' => array('sync_live'),
|
||||
@@ -1524,22 +1676,21 @@ class KalenderLib
|
||||
|
||||
if (!is_null($ort_kurzbz_array))
|
||||
{
|
||||
$new_orte = (array) $ort_kurzbz_array;
|
||||
$new_locations = array_fill(0, count($new_orte), null);
|
||||
$new_orte = (array) ($ort_kurzbz_array['ort_kurzbz'] ?? []);
|
||||
$new_locations = $ort_kurzbz_array['location'] ?? null;
|
||||
}
|
||||
else
|
||||
{
|
||||
$new_orte = (array) $kalender_entry->ort_kurzbz;
|
||||
$new_locations = (array) $kalender_entry->location;
|
||||
$new_locations = $kalender_entry->location;
|
||||
}
|
||||
|
||||
foreach ($new_orte as $index => $ort)
|
||||
foreach ($new_orte as $ort)
|
||||
{
|
||||
$ortresult = $this->_ci->KalenderOrtModel->insert(
|
||||
array(
|
||||
'kalender_id' => $new_kalender_id,
|
||||
'ort_kurzbz' => $ort,
|
||||
'location' => $new_locations[$index] ?? null
|
||||
'ort_kurzbz' => $ort
|
||||
)
|
||||
);
|
||||
|
||||
@@ -1547,6 +1698,19 @@ class KalenderLib
|
||||
return $ortresult;
|
||||
}
|
||||
|
||||
if (!is_null($new_locations))
|
||||
{
|
||||
$locresult = $this->_ci->KalenderOrtModel->insert(
|
||||
array(
|
||||
'kalender_id' => $new_kalender_id,
|
||||
'location' => $new_locations
|
||||
)
|
||||
);
|
||||
|
||||
if (!isSuccess($locresult))
|
||||
return $locresult;
|
||||
}
|
||||
|
||||
return success($new_kalender_id);
|
||||
}
|
||||
private function _loadKalenderEntry($kalender_id)
|
||||
@@ -1569,8 +1733,8 @@ class KalenderLib
|
||||
|
||||
$this->_ci->KalenderModel->addJoin(
|
||||
'(SELECT kalender_id,
|
||||
array_agg(ort_kurzbz ORDER BY ort_kurzbz) AS ort_kurzbz,
|
||||
array_agg(location ORDER BY ort_kurzbz) AS location
|
||||
array_agg(ort_kurzbz ORDER BY ort_kurzbz) FILTER(WHERE ort_kurzbz is NOT NULL) AS ort_kurzbz,
|
||||
MAX(location) AS location
|
||||
FROM lehre.tbl_kalender_ort
|
||||
GROUP BY kalender_id) orte',
|
||||
'tbl_kalender.kalender_id = orte.kalender_id',
|
||||
@@ -1586,7 +1750,7 @@ class KalenderLib
|
||||
$entry = getData($result)[0];
|
||||
$entry->lehreinheit_id = $entry->lehreinheit_id ?? [];
|
||||
$entry->ort_kurzbz = $entry->ort_kurzbz ?? [];
|
||||
$entry->location = $entry->location ?? [];
|
||||
$entry->location = $entry->location ?? null;
|
||||
|
||||
return success($entry);
|
||||
}
|
||||
@@ -1641,44 +1805,76 @@ class KalenderLib
|
||||
|
||||
private function _deleteTypLehreinheit($entry)
|
||||
{
|
||||
$result_lehreinheit = $this->_ci->KalenderLehreinheitModel->loadWhere(array('kalender_id' => $entry->kalender_id));
|
||||
if (isError($result_lehreinheit)) return $result_lehreinheit;
|
||||
$has_lehreinheit = hasData($result_lehreinheit) ? getData($result_lehreinheit)[0] : false;
|
||||
$entryResult = $this->_loadKalenderEntry($entry->kalender_id);
|
||||
|
||||
$result_ort = $this->_ci->KalenderOrtModel->loadWhere(array('kalender_id' => $entry->kalender_id));
|
||||
if (isError($result_ort)) return $result_ort;
|
||||
$has_ort = hasData($result_ort) ? getData($result_ort)[0] : false;
|
||||
|
||||
if ($entry->status_kurzbz === 'planning')
|
||||
if (isError($entryResult)) return $entryResult;
|
||||
|
||||
$kalender_entry = getData($entryResult);
|
||||
|
||||
if (!$this->_checkPermission($kalender_entry->lehreinheit_id))
|
||||
{
|
||||
if ($has_ort)
|
||||
$this->_deleteOrtEntry($has_ort);
|
||||
|
||||
if ($has_lehreinheit)
|
||||
$this->_deleteLehreinheitEntry($has_lehreinheit);
|
||||
|
||||
$this->_ci->KalenderModel->delete(array('tbl_kalender.kalender_id' => $entry->kalender_id));
|
||||
return error([
|
||||
'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
|
||||
'errorCode' => 'not_allowed'
|
||||
]);
|
||||
}
|
||||
else if ($entry->status_kurzbz === 'sync_preview' || $entry->status_kurzbz === 'sync_live')
|
||||
|
||||
|
||||
if ($kalender_entry->status_kurzbz === 'sync_preview' || $kalender_entry->status_kurzbz === 'sync_live' || $kalender_entry->status_kurzbz === 'planning')
|
||||
{
|
||||
$history = $this->getHistory($entry->kalender_id);
|
||||
$history = hasData($history) ? getData($history) : false;
|
||||
$history = $this->getHistory($kalender_entry->kalender_id, false, false);
|
||||
|
||||
if ($has_ort)
|
||||
$result = $this->_deleteOrtEntry($has_ort);
|
||||
$history = hasData($history) && getData($history);
|
||||
|
||||
if ($has_lehreinheit)
|
||||
$result = $this->_deleteLehreinheitEntry($has_lehreinheit);
|
||||
if ($history)
|
||||
{
|
||||
$result = $this->_ci->KalenderModel->update(
|
||||
array('kalender_id' => $kalender_entry->kalender_id),
|
||||
array('status_kurzbz' => 'to_delete','status_kurzbz_max' => 'planning')
|
||||
);
|
||||
|
||||
$this->_ci->KalenderModel->delete(array('tbl_kalender.kalender_id' => $entry->kalender_id));
|
||||
if (isError($result))
|
||||
return error($result);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (!isEmptyArray($kalender_entry->ort_kurzbz))
|
||||
{
|
||||
$result = $this->_deleteOrtEntry($kalender_entry);
|
||||
if (isError($result))
|
||||
return error($result);
|
||||
}
|
||||
|
||||
|
||||
if (!isEmptyArray($kalender_entry->lehreinheit_id))
|
||||
{
|
||||
$result = $this->_deleteLehreinheitEntry($kalender_entry);
|
||||
if (isError($result))
|
||||
return error($result);
|
||||
}
|
||||
|
||||
$result = $this->_ci->KalenderModel->delete(array('tbl_kalender.kalender_id' => $kalender_entry->kalender_id));
|
||||
|
||||
if (isError($result))
|
||||
return error($result);
|
||||
}
|
||||
}
|
||||
else if ($entry->status_kurzbz === 'preview' || $entry->status_kurzbz === 'live')
|
||||
else if ($kalender_entry->status_kurzbz === 'preview' || $kalender_entry->status_kurzbz === 'live')
|
||||
{
|
||||
//TODO (david) überprüfen ob sinnvoll, verschwindet direkt in den ansichten (student, lecturer)
|
||||
if ($kalender_entry->status_kurzbz === 'preview')
|
||||
$new_status = 'to_delete_preview';
|
||||
else
|
||||
$new_status = 'to_delete_live';
|
||||
|
||||
$result = $this->_ci->KalenderModel->update(
|
||||
array('kalender_id' => $entry->kalender_id),
|
||||
array('status_kurzbz' => 'todelete')
|
||||
array('kalender_id' => $kalender_entry->kalender_id),
|
||||
array('status_kurzbz' => $new_status)
|
||||
);
|
||||
|
||||
if (isError($result))
|
||||
return error($result);
|
||||
}
|
||||
|
||||
return success();
|
||||
@@ -1703,11 +1899,11 @@ class KalenderLib
|
||||
return $this->_ci->KalenderEventModel->delete(array('kalender_id' => $entry->kalender_id));
|
||||
}
|
||||
|
||||
public function getHistory($kalender_id, $only_previous = false)
|
||||
public function getHistory($kalender_id, $only_previous = false, $include_self = true)
|
||||
{
|
||||
$dbModel = new DB_Model();
|
||||
$history_entries = $dbModel->execReadOnlyQuery("
|
||||
WITH RECURSIVE
|
||||
$history_sql ="
|
||||
WITH RECURSIVE
|
||||
vorgaenger(kalender_id, vorgaenger_kalender_id) AS (
|
||||
SELECT kalender_id, vorgaenger_kalender_id
|
||||
FROM lehre.tbl_kalender
|
||||
@@ -1746,97 +1942,48 @@ class KalenderLib
|
||||
SELECT kalender_id FROM nachfolger
|
||||
) combined
|
||||
JOIN lehre.tbl_kalender USING(kalender_id)
|
||||
LEFT JOIN orte USING(kalender_id)
|
||||
ORDER BY kalender_id DESC
|
||||
|
||||
" . ($only_previous ? ' LIMIT 1' : ''), array($kalender_id, $kalender_id));
|
||||
LEFT JOIN orte USING(kalender_id)";
|
||||
|
||||
return $history_entries;
|
||||
$params = array($kalender_id, $kalender_id);
|
||||
|
||||
if (!$include_self)
|
||||
{
|
||||
$history_sql .= " WHERE kalender_id != ?";
|
||||
$params[] = $kalender_id;
|
||||
}
|
||||
|
||||
$history_sql .= " ORDER BY kalender_id DESC" . ($only_previous ? ' LIMIT 1' : '');
|
||||
|
||||
return $dbModel->execReadOnlyQuery($history_sql, $params);
|
||||
}
|
||||
|
||||
//TODO in eine eigen Lib?
|
||||
public function sync()
|
||||
private function _checkPermission($lehreinheit_ids)
|
||||
{
|
||||
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
|
||||
if (isEmptyArray($lehreinheit_ids))
|
||||
return true;
|
||||
|
||||
$this->_ci->KalenderModel->addSelect('tbl_kalender.*, tbl_kalender_ort.ort_kurzbz, tbl_kalender_ort.location');
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'tbl_kalender.kalender_id = tbl_kalender_ort.kalender_id', 'LEFT');
|
||||
$this->_ci->KalenderModel->db->where_in('status_kurzbz', array('sync_live', 'sync_preview', 'todelete', 'planning', 'preview'));
|
||||
$this->_ci->KalenderModel->addOrder('tbl_kalender.kalender_id', 'DESC');
|
||||
$to_update = $this->_ci->KalenderModel->load();
|
||||
$allowed = false;
|
||||
|
||||
if (!hasData($to_update))
|
||||
return success();
|
||||
$this->_ci->LehreinheitModel->addSelect('studiengang_kz');
|
||||
$this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrveranstaltung', 'tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id');
|
||||
$this->_ci->LehreinheitModel->db->where_in('lehreinheit_id', $lehreinheit_ids);
|
||||
|
||||
$mail_infos = [];
|
||||
$lehreinheit = $this->_ci->LehreinheitModel->load();
|
||||
if (!hasData($lehreinheit))
|
||||
return error('Lehreinheit nicht gefunden');
|
||||
|
||||
foreach (getData($to_update) as $entry)
|
||||
$studiengaenge = array_unique(array_column(getData($lehreinheit), 'studiengang_kz'));
|
||||
|
||||
foreach ($studiengaenge as $studiengang_kz)
|
||||
{
|
||||
if ($entry->status_kurzbz === 'todelete')
|
||||
if ($this->_ci->permissionlib->isBerechtigt('lehre/lvplan', 'suid', $studiengang_kz))
|
||||
{
|
||||
$this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'deleted'));
|
||||
$this->_archiveVorgaenger($entry->vorgaenger_kalender_id, false);
|
||||
$mail_infos[] = array('entry' => $entry, 'new_status' => 'deleted', 'notify' => array('lektor', 'student'));
|
||||
}
|
||||
|
||||
if ($entry->status_kurzbz === 'sync_preview')
|
||||
{
|
||||
$this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'preview'));
|
||||
$this->_archiveVorgaenger($entry->vorgaenger_kalender_id, true);
|
||||
$mail_infos[] = array('entry' => $entry, 'new_status' => 'preview', 'notify' => array('lektor'));
|
||||
}
|
||||
|
||||
if ($entry->status_kurzbz === 'sync_live' || $entry->status_kurzbz === 'planning')
|
||||
{
|
||||
$this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'live'));
|
||||
$this->_archiveVorgaenger($entry->vorgaenger_kalender_id, false);
|
||||
$mail_infos[] = array('entry' => $entry, 'new_status' => 'live', 'notify' => array('lektor', 'student'));
|
||||
}
|
||||
|
||||
if ($entry->status_kurzbz === 'preview')
|
||||
{
|
||||
$current = getData($this->_ci->KalenderModel->load(array('kalender_id' => $entry->kalender_id)))[0];
|
||||
if ($current->status_kurzbz === 'archived')
|
||||
continue;
|
||||
|
||||
$this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'live'));
|
||||
$this->_archiveVorgaenger($entry->vorgaenger_kalender_id, false);
|
||||
$mail_infos[] = array('entry' => $entry, 'new_status' => 'live', 'notify' => array('lektor', 'student'));
|
||||
$allowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_ci->load->library('KalenderNotificationLib');
|
||||
$this->_ci->kalendernotificationlib->sendMails($mail_infos);
|
||||
return success();
|
||||
|
||||
}
|
||||
|
||||
private function _archiveVorgaenger($vorgaenger_kalender_id, $stop_at_live = false)
|
||||
{
|
||||
if (!$vorgaenger_kalender_id) return;
|
||||
|
||||
$current_id = $vorgaenger_kalender_id;
|
||||
|
||||
while ($current_id)
|
||||
{
|
||||
$vorgaenger = $this->_ci->KalenderModel->load(array('kalender_id' => $current_id));
|
||||
if (!hasData($vorgaenger)) return;
|
||||
|
||||
$vorgaenger = getData($vorgaenger)[0];
|
||||
|
||||
if ($stop_at_live && $vorgaenger->status_kurzbz === 'live')
|
||||
return;
|
||||
|
||||
if (in_array($vorgaenger->status_kurzbz, array('preview', 'live')))
|
||||
{
|
||||
$this->_ci->KalenderModel->update(
|
||||
array('kalender_id' => $current_id),
|
||||
array('status_kurzbz' => 'archived')
|
||||
);
|
||||
}
|
||||
|
||||
$current_id = $vorgaenger->vorgaenger_kalender_id;
|
||||
}
|
||||
return $allowed;
|
||||
}
|
||||
|
||||
private function getLanguageIndex()
|
||||
|
||||
@@ -10,7 +10,7 @@ class KalenderNotificationLib
|
||||
$this->_ci =& get_instance();
|
||||
$this->_ci->load->library('MailLib');
|
||||
$this->_ci->load->config('tempus');
|
||||
|
||||
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
|
||||
}
|
||||
|
||||
public function sendMails($mail_infos)
|
||||
@@ -90,6 +90,7 @@ class KalenderNotificationLib
|
||||
if (!empty($student_deleted))
|
||||
$student_entries .= $this->_addToList($student_deleted, 'gelöscht') . '<hr/>';
|
||||
|
||||
//TODO (david) richtigen Empfänger
|
||||
if (!empty($lektor_entries))
|
||||
$this->_ci->maillib->send('', '[email protected]', 'Lektor Tempus Update', $lektor_entries);
|
||||
if (!empty($student_entries))
|
||||
|
||||
@@ -0,0 +1,429 @@
|
||||
<?php
|
||||
|
||||
if (! defined("BASEPATH")) exit("No direct script access allowed");
|
||||
|
||||
class KalenderSyncLib
|
||||
{
|
||||
private $_ci;
|
||||
|
||||
private $status_map = array(
|
||||
'preview' => array('planning', 'sync_preview'),
|
||||
'live' => array('planning', 'sync_preview', 'preview', 'sync_live')
|
||||
);
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->_ci =& get_instance();
|
||||
|
||||
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
|
||||
$this->_ci->load->model('ressource/Kalendersyncstatus_model', 'KalendersyncstatusModel');
|
||||
$this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
|
||||
$this->_ci->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
|
||||
$this->_ci->load->library('KalenderLib');
|
||||
}
|
||||
|
||||
public function run($studiensemester_kurzbz)
|
||||
{
|
||||
$this->_ci->KalendersyncstatusModel->db->where('studiensemester_kurzbz', $studiensemester_kurzbz);
|
||||
|
||||
$configs = $this->_ci->KalendersyncstatusModel->load();
|
||||
|
||||
if (isError($configs))
|
||||
return $configs;
|
||||
|
||||
if (!hasData($configs))
|
||||
return success([]);
|
||||
|
||||
$results = [];
|
||||
$mail_infos_gesamt = [];
|
||||
|
||||
foreach (getData($configs) as $config)
|
||||
{
|
||||
|
||||
$ziel_status = isEmptyString($config->sync_status_kurzbz) ? 'live' : $config->sync_status_kurzbz;
|
||||
|
||||
$relevante_stati = array_merge($this->status_map[$ziel_status], array('to_delete', 'to_delete_live', 'to_delete_preview'));
|
||||
|
||||
$kalender_ids_result = $this->getKalenderIds(
|
||||
$config->oe_kurzbz,
|
||||
$config->studiensemester_kurzbz,
|
||||
$relevante_stati,
|
||||
$config->ausbildungssemester,
|
||||
$config->studienplan_id,
|
||||
$config->datum_bis
|
||||
);
|
||||
|
||||
if (isError($kalender_ids_result))
|
||||
return $kalender_ids_result;
|
||||
|
||||
$kalender_ids = getData($kalender_ids_result);
|
||||
|
||||
$sync_result = $this->_syncKalenderIds($kalender_ids, $ziel_status);
|
||||
|
||||
if (isError($sync_result))
|
||||
return $sync_result;
|
||||
|
||||
$sync_data = getData($sync_result);
|
||||
|
||||
if ((bool) $config->mail)
|
||||
$mail_infos_gesamt = array_merge($mail_infos_gesamt, $sync_data['mail_infos']);
|
||||
|
||||
$results[] = [
|
||||
'kalender_syncstatus_id' => $config->kalender_syncstatus_id,
|
||||
'oe_kurzbz' => $config->oe_kurzbz,
|
||||
'ausbildungssemester' => $config->ausbildungssemester,
|
||||
'studienplan_id' => $config->studienplan_id,
|
||||
'ziel_status' => $ziel_status,
|
||||
'mail' => (bool) $config->mail,
|
||||
'synced' => $sync_data['synced']
|
||||
];
|
||||
}
|
||||
|
||||
if (!empty($mail_infos_gesamt))
|
||||
{
|
||||
$this->_ci->load->library('KalenderNotificationLib');
|
||||
$this->_ci->kalendernotificationlib->sendMails($mail_infos_gesamt);
|
||||
}
|
||||
|
||||
return success($results);
|
||||
}
|
||||
|
||||
public function runManual($oe_kurzbz, $studiensemester_kurzbz, $ausbildungssemester = null, $studienplan_id = null, $mail = true, $datum_bis = null, $ziel_status = 'live')
|
||||
{
|
||||
$relevante_stati = array_merge($this->status_map[$ziel_status], array('to_delete', 'to_delete_live', 'to_delete_preview'));
|
||||
|
||||
$kalender_ids_result = $this->getKalenderIds(
|
||||
$oe_kurzbz,
|
||||
$studiensemester_kurzbz,
|
||||
$relevante_stati,
|
||||
$ausbildungssemester,
|
||||
$studienplan_id,
|
||||
$datum_bis
|
||||
);
|
||||
|
||||
if (isError($kalender_ids_result))
|
||||
return $kalender_ids_result;
|
||||
|
||||
$kalender_ids = getData($kalender_ids_result);
|
||||
|
||||
$sync_result = $this->_syncKalenderIds($kalender_ids, $ziel_status);
|
||||
|
||||
if (isError($sync_result))
|
||||
return $sync_result;
|
||||
|
||||
$sync_data = getData($sync_result);
|
||||
|
||||
if ($mail && !empty($sync_data['mail_infos']))
|
||||
{
|
||||
$this->_ci->load->library('KalenderNotificationLib');
|
||||
$this->_ci->kalendernotificationlib->sendMails($sync_data['mail_infos']);
|
||||
}
|
||||
|
||||
return success(['synced' => $sync_data['synced']]);
|
||||
}
|
||||
|
||||
public function sync()
|
||||
{
|
||||
$mail_infos_gesamt = [];
|
||||
$synced_gesamt = 0;
|
||||
|
||||
$todelete_ids_result = $this->_getManuallySetStatus(array('to_delete', 'to_delete_live', 'to_delete_preview'));
|
||||
|
||||
if (isError($todelete_ids_result))
|
||||
return $todelete_ids_result;
|
||||
|
||||
$todelete_result = $this->_syncKalenderIds(getData($todelete_ids_result), null);
|
||||
|
||||
if (isError($todelete_result))
|
||||
return $todelete_result;
|
||||
|
||||
$todelete_data = getData($todelete_result);
|
||||
$mail_infos_gesamt = array_merge($mail_infos_gesamt, $todelete_data['mail_infos']);
|
||||
$synced_gesamt += $todelete_data['synced'];
|
||||
|
||||
$preview_ids_result = $this->_getManuallySetStatus(array('sync_preview'));
|
||||
|
||||
if (isError($preview_ids_result))
|
||||
return $preview_ids_result;
|
||||
|
||||
$preview_result = $this->_syncKalenderIds(getData($preview_ids_result), 'preview');
|
||||
|
||||
if (isError($preview_result))
|
||||
return $preview_result;
|
||||
|
||||
$preview_data = getData($preview_result);
|
||||
$mail_infos_gesamt = array_merge($mail_infos_gesamt, $preview_data['mail_infos']);
|
||||
$synced_gesamt += $preview_data['synced'];
|
||||
|
||||
$live_ids_result = $this->_getManuallySetStatus(array('sync_live'));
|
||||
|
||||
if (isError($live_ids_result))
|
||||
return $live_ids_result;
|
||||
|
||||
$live_result = $this->_syncKalenderIds(getData($live_ids_result), 'live');
|
||||
|
||||
if (isError($live_result))
|
||||
return $live_result;
|
||||
|
||||
$live_data = getData($live_result);
|
||||
$mail_infos_gesamt = array_merge($mail_infos_gesamt, $live_data['mail_infos']);
|
||||
$synced_gesamt += $live_data['synced'];
|
||||
|
||||
if (!empty($mail_infos_gesamt))
|
||||
{
|
||||
$this->_ci->load->library('KalenderNotificationLib');
|
||||
$this->_ci->kalendernotificationlib->sendMails($mail_infos_gesamt);
|
||||
}
|
||||
|
||||
return success(['synced' => $synced_gesamt]);
|
||||
}
|
||||
|
||||
private function _getManuallySetStatus($status_kurzbz_list)
|
||||
{
|
||||
if (empty($status_kurzbz_list))
|
||||
return success([]);
|
||||
|
||||
$this->_ci->KalenderModel->addSelect('tbl_kalender.kalender_id');
|
||||
$this->_ci->KalenderModel->db->where_in('status_kurzbz', $status_kurzbz_list);
|
||||
$result = $this->_ci->KalenderModel->load();
|
||||
|
||||
if (isError($result))
|
||||
return $result;
|
||||
|
||||
if (!hasData($result))
|
||||
return success([]);
|
||||
|
||||
return success(array_column(getData($result), 'kalender_id'));
|
||||
}
|
||||
|
||||
public function getKalenderIds($oe_kurzbz, $studiensemester_kurzbz, $status_kurzbz_list, $ausbildungssemester = null, $studienplan_id = null, $datum_bis = null)
|
||||
{
|
||||
if (empty($status_kurzbz_list))
|
||||
return success([]);
|
||||
|
||||
$studiengang_result = $this->_getStudiengang($oe_kurzbz);
|
||||
|
||||
if (isError($studiengang_result))
|
||||
return $studiengang_result;
|
||||
|
||||
$studiengang_kz = getData($studiengang_result);
|
||||
|
||||
if (!hasData($studiengang_result))
|
||||
{
|
||||
$organisationseinheiten = $this->_ci->OrganisationseinheitModel->getChilds($oe_kurzbz);
|
||||
$oe_kurzbz = hasData($organisationseinheiten) ? array_column(getData($organisationseinheiten), 'oe_kurzbz') : [];
|
||||
}
|
||||
|
||||
$this->_ci->KalenderModel->addDistinct('tbl_kalender.kalender_id');
|
||||
$this->_ci->KalenderModel->addSelect('tbl_kalender.kalender_id');
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit', 'tbl_kalender.kalender_id = tbl_kalender_lehreinheit.kalender_id');
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheit', 'tbl_kalender_lehreinheit.lehreinheit_id = tbl_lehreinheit.lehreinheit_id');
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehrveranstaltung', 'tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id');
|
||||
|
||||
if (!is_null($studiengang_kz))
|
||||
{
|
||||
$this->_ci->KalenderModel->db->where('tbl_lehrveranstaltung.studiengang_kz', $studiengang_kz);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->_ci->KalenderModel->db->where_in('tbl_lehrveranstaltung.oe_kurzbz', $oe_kurzbz);
|
||||
}
|
||||
|
||||
$this->_ci->KalenderModel->db->where('tbl_lehreinheit.studiensemester_kurzbz', $studiensemester_kurzbz);
|
||||
$this->_ci->KalenderModel->db->where_in('tbl_kalender.status_kurzbz', $status_kurzbz_list);
|
||||
|
||||
$this->_ci->KalenderModel->db->where('NOT EXISTS (
|
||||
SELECT 1 FROM lehre.tbl_kalender nachfolger
|
||||
WHERE nachfolger.vorgaenger_kalender_id = tbl_kalender.kalender_id)', null, false);
|
||||
|
||||
if (!is_null($studienplan_id))
|
||||
{
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_studienplan_lehrveranstaltung', 'tbl_lehrveranstaltung.lehrveranstaltung_id = tbl_studienplan_lehrveranstaltung.lehrveranstaltung_id');
|
||||
$this->_ci->KalenderModel->db->where('tbl_studienplan_lehrveranstaltung.studienplan_id', $studienplan_id);
|
||||
}
|
||||
|
||||
if (!is_null($ausbildungssemester))
|
||||
$this->_ci->KalenderModel->db->where('tbl_lehrveranstaltung.semester', $ausbildungssemester);
|
||||
|
||||
if (!is_null($datum_bis))
|
||||
{
|
||||
$end_date = date('Y-m-d', strtotime($datum_bis . ' +1 day'));
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.von <', $end_date);
|
||||
}
|
||||
|
||||
$result = $this->_ci->KalenderModel->load();
|
||||
|
||||
if (isError($result))
|
||||
return $result;
|
||||
|
||||
if (!hasData($result))
|
||||
return success([]);
|
||||
|
||||
return success(array_column(getData($result), 'kalender_id'));
|
||||
}
|
||||
|
||||
|
||||
private function _archiveVorgaenger($vorgaenger_kalender_id, $stop_at_live = false)
|
||||
{
|
||||
$return_array = array();
|
||||
if (!$vorgaenger_kalender_id) return success($return_array);
|
||||
|
||||
$current_id = $vorgaenger_kalender_id;
|
||||
|
||||
while ($current_id)
|
||||
{
|
||||
$vorgaenger = $this->_ci->KalenderModel->load(array('kalender_id' => $current_id));
|
||||
if (!hasData($vorgaenger)) return success($return_array);
|
||||
|
||||
$vorgaenger = getData($vorgaenger)[0];
|
||||
|
||||
if ($stop_at_live && $vorgaenger->status_kurzbz === 'live')
|
||||
return success($return_array);
|
||||
|
||||
if (in_array($vorgaenger->status_kurzbz, array('preview', 'live')))
|
||||
{
|
||||
$this->_ci->KalenderModel->update(
|
||||
array('kalender_id' => $current_id),
|
||||
array('status_kurzbz' => 'archived', 'status_kurzbz_max' => $vorgaenger->status_kurzbz)
|
||||
);
|
||||
|
||||
$return_array[] = $vorgaenger;
|
||||
}
|
||||
|
||||
$current_id = $vorgaenger->vorgaenger_kalender_id;
|
||||
}
|
||||
return success($return_array);
|
||||
}
|
||||
|
||||
private function _syncKalenderIds($kalender_ids, $ziel_status)
|
||||
{
|
||||
if (empty($kalender_ids))
|
||||
return success(['synced' => 0, 'mail_infos' => []]);
|
||||
|
||||
$this->_ci->KalenderModel->addSelect('tbl_kalender.*, tbl_kalender_ort.ort_kurzbz, tbl_kalender_ort.location');
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'tbl_kalender.kalender_id = tbl_kalender_ort.kalender_id', 'LEFT');
|
||||
$this->_ci->KalenderModel->db->where_in('tbl_kalender.kalender_id', $kalender_ids);
|
||||
$this->_ci->KalenderModel->addOrder('tbl_kalender.kalender_id', 'DESC');
|
||||
$to_update = $this->_ci->KalenderModel->load();
|
||||
|
||||
if (isError($to_update))
|
||||
return $to_update;
|
||||
|
||||
if (!hasData($to_update))
|
||||
return success(['synced' => 0, 'mail_infos' => []]);
|
||||
|
||||
$mail_infos = [];
|
||||
$synced = 0;
|
||||
|
||||
foreach (getData($to_update) as $entry)
|
||||
{
|
||||
if (in_array($entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview')))
|
||||
{
|
||||
$notify = array();
|
||||
if ($entry->status_kurzbz === 'to_delete_live')
|
||||
{
|
||||
$status_max = 'live';
|
||||
$notify = array('lektor', 'student');
|
||||
}
|
||||
else if ($entry->status_kurzbz === 'to_delete_preview')
|
||||
{
|
||||
$status_max = 'preview';
|
||||
$notify = array('lektor');
|
||||
}
|
||||
else if ($entry->status_kurzbz === 'to_delete')
|
||||
{
|
||||
$status_max = 'planning';
|
||||
}
|
||||
|
||||
$this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'deleted', 'status_kurzbz_max' => $status_max));
|
||||
$mail_infos[] = array('entry' => $entry, 'new_status' => 'deleted', 'notify' => $notify);
|
||||
|
||||
$vorgaenger_array = $this->_archiveVorgaenger($entry->vorgaenger_kalender_id);
|
||||
|
||||
|
||||
|
||||
if (hasData($vorgaenger_array))
|
||||
{
|
||||
foreach(getData($vorgaenger_array) as $vorgaenger)
|
||||
{
|
||||
$archive_notify = array();
|
||||
|
||||
if ($vorgaenger->status_kurzbz === 'preview')
|
||||
$archive_notify = array('lektor');
|
||||
else if ($vorgaenger->status_kurzbz === 'live')
|
||||
{
|
||||
$archive_notify = array('student', 'lektor');
|
||||
|
||||
$history = $this->_ci->kalenderlib->getHistory($vorgaenger->kalender_id, false, false);
|
||||
if (hasData($history))
|
||||
{
|
||||
$history = getData($history);
|
||||
|
||||
foreach ($history as $entry)
|
||||
{
|
||||
if ($entry->status_kurzbz === 'deleted' && $entry->status_kurzbz_max === 'preview')
|
||||
{
|
||||
$archive_notify = array('student');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$mail_infos[] = array('entry' => $vorgaenger, 'new_status' => 'deleted', 'notify' => $archive_notify);
|
||||
}
|
||||
}
|
||||
|
||||
$synced++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($ziel_status === 'preview' && in_array($entry->status_kurzbz, array('planning', 'sync_preview')))
|
||||
{
|
||||
$this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'preview'));
|
||||
$this->_archiveVorgaenger($entry->vorgaenger_kalender_id, true);
|
||||
$mail_infos[] = array('entry' => $entry, 'new_status' => 'preview', 'notify' => array('lektor'));
|
||||
$synced++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($ziel_status === 'live' && in_array($entry->status_kurzbz, array('planning', 'sync_preview', 'sync_live')))
|
||||
{
|
||||
$this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'live'));
|
||||
$this->_archiveVorgaenger($entry->vorgaenger_kalender_id, false);
|
||||
$mail_infos[] = array('entry' => $entry, 'new_status' => 'live', 'notify' => array('lektor', 'student'));
|
||||
$synced++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($ziel_status === 'live' && $entry->status_kurzbz === 'preview')
|
||||
{
|
||||
$current = getData($this->_ci->KalenderModel->load(array('kalender_id' => $entry->kalender_id)))[0];
|
||||
if ($current->status_kurzbz === 'archived')
|
||||
continue;
|
||||
|
||||
$this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'live'));
|
||||
$this->_archiveVorgaenger($entry->vorgaenger_kalender_id, false);
|
||||
$mail_infos[] = array('entry' => $entry, 'new_status' => 'live', 'notify' => array('lektor', 'student'));
|
||||
$synced++;
|
||||
}
|
||||
}
|
||||
|
||||
return success(['synced' => $synced, 'mail_infos' => $mail_infos]);
|
||||
}
|
||||
|
||||
|
||||
private function _getStudiengang($oe_kurzbz)
|
||||
{
|
||||
$this->_ci->StudiengangModel->addJoin('tbl_organisationseinheit', 'oe_kurzbz');
|
||||
$result = $this->_ci->StudiengangModel->loadWhere(array('oe_kurzbz' => $oe_kurzbz));
|
||||
|
||||
if (isError($result))
|
||||
return $result;
|
||||
|
||||
if (!hasData($result))
|
||||
return success(null);
|
||||
|
||||
return success(getData($result)[0]->studiengang_kz);
|
||||
}
|
||||
}
|
||||
@@ -22,13 +22,14 @@ class RaumvorschlagLib
|
||||
$this->_ci->load->model('ressource/Ort_model', 'OrtModel');
|
||||
$this->_ci->load->model('organisation/gruppe_model', 'GruppeModel');
|
||||
$this->_ci->load->model('organisation/Lehrverband_model', 'LehrverbandModel');
|
||||
|
||||
$this->_ci->load->model('education/Lehreinheitgruppe_model', 'LehreinheitgruppeModel');
|
||||
$this->_ci->load->model('ressource/Zeitsperre_model', 'ZeitsperreModel');
|
||||
$this->_ci->load->model('ressource/Stunde_model', 'StundeModel');
|
||||
$this->_ci->load->model('education/Lehreinheitgruppe_model', 'LehreinheitgruppeModel');
|
||||
|
||||
$this->_ci->load->library('CollisionChecker');
|
||||
$this->_ci->load->library('KalenderLib');
|
||||
$this->_ci->load->library('PhrasesLib', array('ui'));
|
||||
$this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
|
||||
}
|
||||
|
||||
|
||||
@@ -36,47 +37,295 @@ class RaumvorschlagLib
|
||||
{
|
||||
$event = $this->_ci->kalenderlib->getByKalenderId($kalender_id);
|
||||
$event = $event[0];
|
||||
return $this->_getVorschlaegeForEvent($event);
|
||||
}
|
||||
|
||||
$lektor_uids = array_column($event->lektor, 'mitarbeiter_uid');
|
||||
$gruppen_kurzbz = array_values(array_filter(array_column($event->gruppe, 'gruppe_kurzbz')));
|
||||
public function getVorschlaegeByLehreinheit($lehreinheit_id, $von, $bis)
|
||||
{
|
||||
$teilnehmer = $this->_getLehreinheitTeilnehmer($lehreinheit_id);
|
||||
|
||||
$lehrverband_gruppen = array_values(array_filter($event->gruppe, function($gruppe)
|
||||
$event = (object) [
|
||||
'kalender_id' => null,
|
||||
'lehreinheit_id' => [$lehreinheit_id],
|
||||
'isostart' => (new DateTime($von))->format('c'),
|
||||
'isoend' => (new DateTime($bis))->format('c'),
|
||||
'datum' => (new DateTime($von))->format('Y-m-d'),
|
||||
'lektor' => $teilnehmer->lektor_data,
|
||||
'gruppe' => $teilnehmer->gruppen_data,
|
||||
];
|
||||
|
||||
return $this->_getVorschlaegeForEvent($event);
|
||||
}
|
||||
|
||||
public function getVorschlaegeSlots($lehreinheit_id, $start_date, $end_date)
|
||||
{
|
||||
$lehreinheit_result = $this->_ci->LehreinheitModel->load($lehreinheit_id);
|
||||
if (!hasData($lehreinheit_result))
|
||||
return error('Lehreinheit nicht gefunden');
|
||||
$lehreinheit = getData($lehreinheit_result)[0];
|
||||
|
||||
$block = $lehreinheit->stundenblockung;
|
||||
if ($block <= 0)
|
||||
return error('Stundenblockung ist ungültig');
|
||||
|
||||
$this->_ci->StundeModel->addOrder('stunde', 'ASC');
|
||||
$stunden_result = $this->_ci->StundeModel->load();
|
||||
$stunden = hasData($stunden_result) ? array_values(getData($stunden_result)) : [];
|
||||
|
||||
if (empty($stunden))
|
||||
return error('Kein Stunden-Raster gefunden');
|
||||
|
||||
$teilnehmer = $this->_getLehreinheitTeilnehmer($lehreinheit_id);
|
||||
$grp = $this->_splitGruppen($teilnehmer->gruppen_data);
|
||||
$lektor_uids = array_column($teilnehmer->lektor_data, 'mitarbeiter_uid');
|
||||
|
||||
$verplante_events = $this->_ci->kalenderlib->getForRaumvorschlag(
|
||||
$start_date,
|
||||
$end_date,
|
||||
$lektor_uids,
|
||||
$grp->gruppen_kurzbz,
|
||||
$grp->lehrverband_gruppen
|
||||
);
|
||||
|
||||
$start_day = strtotime($start_date);
|
||||
$end_day = strtotime($end_date);
|
||||
|
||||
$moegliche_slots = array();
|
||||
|
||||
$verplante_zeitsperren = $this->_getZeitsperen($start_date, $end_date, $lektor_uids);
|
||||
while ($start_day <= $end_day)
|
||||
{
|
||||
$tag = date('Y-m-d', $start_day);
|
||||
|
||||
$verplante_tages_events = array_values(array_filter($verplante_events, function($event) use ($tag)
|
||||
{
|
||||
return $event->datum === $tag;
|
||||
}));
|
||||
|
||||
foreach ($stunden as $index => $start_stunde)
|
||||
{
|
||||
if (!isset($stunden[$index + $block - 1]))
|
||||
continue;
|
||||
|
||||
$end_stunde = $stunden[$index + $block - 1];
|
||||
|
||||
$slot_start = $tag . ' ' . $start_stunde->beginn;
|
||||
$slot_end = $tag . ' ' . $end_stunde->ende;
|
||||
|
||||
if (!$this->_isFrei($slot_start, $slot_end, $verplante_zeitsperren, $lektor_uids, 'lektor'))
|
||||
continue;
|
||||
|
||||
if (!$this->_isFrei($slot_start, $slot_end, $verplante_tages_events, $lektor_uids, 'lektor'))
|
||||
continue;
|
||||
|
||||
if (!$this->_isFrei($slot_start, $slot_end, $verplante_tages_events, $grp->gruppen_kurzbz, 'gruppe'))
|
||||
continue;
|
||||
|
||||
if (!$this->_isFrei($slot_start, $slot_end, $verplante_tages_events, $grp->lehrverband_gruppen_bezeichnung, 'lehrverband'))
|
||||
continue;
|
||||
|
||||
$moegliche_slots[] = [
|
||||
'isostart' => (new DateTime($slot_start))->format('c'),
|
||||
'isoend' => (new DateTime($slot_end))->format('c'),
|
||||
'marker_isoend' => (new DateTime($tag . ' ' . $start_stunde->ende))->format('c'),
|
||||
];
|
||||
}
|
||||
|
||||
$start_day = strtotime('+1 day', $start_day);
|
||||
}
|
||||
|
||||
|
||||
$slots = [];
|
||||
foreach ($moegliche_slots as $slot)
|
||||
{
|
||||
$event_obj = (object) [
|
||||
'kalender_id' => null,
|
||||
'lehreinheit_id' => [$lehreinheit_id],
|
||||
'isostart' => $slot['isostart'],
|
||||
'isoend' => $slot['isoend'],
|
||||
];
|
||||
|
||||
$raumkandidaten = $this->_getRaumkandidaten($event_obj);
|
||||
|
||||
if (empty($raumkandidaten))
|
||||
continue;
|
||||
|
||||
$ratings = $this->_getRatings($verplante_events, $slot, $raumkandidaten, $lektor_uids, $grp->gruppen_kurzbz, $grp->lehrverband_gruppen_bezeichnung);
|
||||
$best = $ratings[0];
|
||||
$anzahl_weitere = count($ratings) - 1;
|
||||
|
||||
$slots[] = [
|
||||
'isostart' => $slot['isostart'],
|
||||
'isoend' => $slot['isoend'],
|
||||
'marker_isoend' => $slot['marker_isoend'],
|
||||
'rating' => $this->_scoreToRating($best['score']),
|
||||
'label' => $anzahl_weitere > 0 ? $best['ort_kurzbz'] . ' (' . $best['score'] . ') + ' . $anzahl_weitere . ' weitere' : $best['ort_kurzbz'] . ' (' . $best['score'] . ')',
|
||||
'raeume' => $ratings,
|
||||
];
|
||||
}
|
||||
return success($slots);
|
||||
}
|
||||
|
||||
private function _getZeitsperen($start_date, $end_date, $uids)
|
||||
{
|
||||
|
||||
if (empty($uids)) return [];
|
||||
|
||||
if (($this->_ci->variablelib->getVar('ignore_kollision') === 'true') || ($this->_ci->variablelib->getVar('ignore_zeitsperre') === 'true')) return [];
|
||||
|
||||
|
||||
$this->_ci->ZeitsperreModel->addSelect('mitarbeiter_uid, vondatum, vonstunde_z.beginn as von_beginn, bisdatum, bisstunde_z.ende as bis_ende');
|
||||
$this->_ci->ZeitsperreModel->addJoin('lehre.tbl_stunde vonstunde_z', 'vonstunde_z.stunde = tbl_zeitsperre.vonstunde', 'LEFT');
|
||||
$this->_ci->ZeitsperreModel->addJoin('lehre.tbl_stunde bisstunde_z', 'bisstunde_z.stunde = tbl_zeitsperre.bisstunde', 'LEFT');
|
||||
$this->_ci->ZeitsperreModel->db->where('zeitsperretyp_kurzbz !=', 'ZVerfueg');
|
||||
$this->_ci->ZeitsperreModel->db->where('(tbl_zeitsperre.vondatum + COALESCE(vonstunde_z.beginn, \'00:00\'))::timestamp <', $end_date);
|
||||
$this->_ci->ZeitsperreModel->db->where('(tbl_zeitsperre.bisdatum + COALESCE(bisstunde_z.ende, \'23:59\'))::timestamp >', $start_date);
|
||||
|
||||
$this->_ci->ZeitsperreModel->db->where_in('mitarbeiter_uid', $uids);
|
||||
$result = $this->_ci->ZeitsperreModel->load();
|
||||
|
||||
if (!hasData($result)) return [];
|
||||
|
||||
$events = [];
|
||||
foreach (getData($result) as $row)
|
||||
{
|
||||
$von = new DateTime($row->vondatum . ' ' . ($row->von_beginn ?? '00:00'));
|
||||
$bis = new DateTime($row->bisdatum . ' ' . ($row->bis_ende ?? '23:59'));
|
||||
|
||||
$events[] = (object)[
|
||||
'isostart' => $von->format('c'),
|
||||
'isoend' => $bis->format('c'),
|
||||
'lektor' => [['mitarbeiter_uid' => $row->mitarbeiter_uid]]
|
||||
];
|
||||
}
|
||||
return $events;
|
||||
}
|
||||
|
||||
private function _getLehreinheitTeilnehmer($lehreinheit_id)
|
||||
{
|
||||
$lektoren_result = $this->_ci->LehreinheitMitarbeiterModel->loadWhere(['lehreinheit_id' => $lehreinheit_id]);
|
||||
$lektor_data = [];
|
||||
if (hasData($lektoren_result))
|
||||
{
|
||||
$lektor_data = getData($lektoren_result);
|
||||
}
|
||||
|
||||
$gruppen_result = $this->_ci->LehreinheitgruppeModel->getByLehreinheit($lehreinheit_id);
|
||||
$gruppen_data = [];
|
||||
if (hasData($gruppen_result))
|
||||
{
|
||||
$gruppen_rows = getData($gruppen_result);
|
||||
|
||||
foreach ($gruppen_rows as $gruppe)
|
||||
{
|
||||
$gruppen_data[] = (array) $gruppe;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (object)[
|
||||
'lektor_data' => $lektor_data,
|
||||
'gruppen_data' => $gruppen_data,
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
private function _splitGruppen($gruppen_data)
|
||||
{
|
||||
$gruppen_kurzbz = array_values(array_filter(array_column($gruppen_data, 'gruppe_kurzbz')));
|
||||
$lehrverband_gruppen = array_values(array_filter($gruppen_data, function($gruppe)
|
||||
{
|
||||
return empty($gruppe['gruppe_kurzbz']);
|
||||
}));
|
||||
$lehrverband_gruppen_bezeichnung = array_column($lehrverband_gruppen, 'bezeichnung');
|
||||
|
||||
return (object)[
|
||||
'gruppen_kurzbz' => $gruppen_kurzbz,
|
||||
'lehrverband_gruppen' => $lehrverband_gruppen,
|
||||
'lehrverband_gruppen_bezeichnung' => $lehrverband_gruppen_bezeichnung
|
||||
];
|
||||
|
||||
}
|
||||
//TODO (david) umbauen auf CollisionChecks
|
||||
private function _isFrei($slot_start, $slot_end, $events, $check_array, $type)
|
||||
{
|
||||
if (empty($check_array)) return true;
|
||||
|
||||
$slot_start_ts = strtotime($slot_start);
|
||||
$slot_end_ts = strtotime($slot_end);
|
||||
|
||||
foreach ($events as $event)
|
||||
{
|
||||
$event_start_ts = strtotime($event->isostart);
|
||||
$event_end_ts = strtotime($event->isoend);
|
||||
|
||||
if ($event_end_ts <= $slot_start_ts || $event_start_ts >= $slot_end_ts)
|
||||
continue;
|
||||
|
||||
$event_uids = $this->_getIds($event, $type);
|
||||
|
||||
if (!empty(array_intersect($event_uids, $check_array)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function _scoreToRating($score)
|
||||
{
|
||||
if ($score >= 90)
|
||||
return 'good';
|
||||
if ($score >= 60)
|
||||
return 'mid';
|
||||
return 'bad';
|
||||
}
|
||||
private function _getVorschlaegeForEvent($event)
|
||||
{
|
||||
$raumkandidaten = $this->_getRaumkandidaten($event);
|
||||
if (empty($raumkandidaten)) return [];
|
||||
|
||||
$lektor_uids = array_column($event->lektor, 'mitarbeiter_uid');
|
||||
$grp = $this->_splitGruppen($event->gruppe);
|
||||
|
||||
$tages_events = $this->_ci->kalenderlib->getForRaumvorschlag(
|
||||
$event->datum,
|
||||
$event->datum,
|
||||
$lektor_uids,
|
||||
$gruppen_kurzbz,
|
||||
$lehrverband_gruppen
|
||||
$grp->gruppen_kurzbz,
|
||||
$grp->lehrverband_gruppen
|
||||
);
|
||||
|
||||
$lektor_davor = $this->_getEventDavor($tages_events, $event->isostart, $lektor_uids, 'lektor');
|
||||
$gruppen_davor = $this->_getEventDavor($tages_events, $event->isostart, $gruppen_kurzbz, 'gruppe');
|
||||
return $this->_getRatings($tages_events, $event, $raumkandidaten, $lektor_uids, $grp->gruppen_kurzbz, $grp->lehrverband_gruppen_bezeichnung);
|
||||
}
|
||||
private function _getRatings($events, $event, $raumkandidaten, $lektor_uids, $gruppen_kurzbz, $lehrverband_gruppen_bezeichnung)
|
||||
{
|
||||
$event = (object)$event;
|
||||
$lektor_davor = $this->_getEventDavor($events, $event->isostart, $lektor_uids, 'lektor');
|
||||
$gruppen_davor = $this->_getEventDavor($events, $event->isostart, $gruppen_kurzbz, 'gruppe');
|
||||
$lehrverband_davor = $this->_getEventDavor($events, $event->isostart, $lehrverband_gruppen_bezeichnung, 'lehrverband');
|
||||
|
||||
$lektor_davor_ort = $lektor_davor ? $this->_getOrtDetails($lektor_davor->ort_kurzbz) : null;
|
||||
$gruppen_davor_ort = $gruppen_davor ? $this->_getOrtDetails($gruppen_davor->ort_kurzbz) : null;
|
||||
|
||||
$kandidaten = $this->_getRaumkandidaten($event);
|
||||
if (empty($kandidaten)) return [];
|
||||
$lehrverband_davor_ort = $lehrverband_davor ? $this->_getOrtDetails($lehrverband_davor->ort_kurzbz) : null;
|
||||
|
||||
$unique = [];
|
||||
|
||||
foreach ($kandidaten as $raum)
|
||||
foreach ($raumkandidaten as $raum)
|
||||
{
|
||||
$unique[$raum->ort_kurzbz] = $raum;
|
||||
}
|
||||
|
||||
$kandidaten = array_values($unique);
|
||||
|
||||
|
||||
$ratings = [];
|
||||
foreach ($kandidaten as $raum)
|
||||
{
|
||||
$rating = ['ort_kurzbz' => $raum->ort_kurzbz, 'score' => 100, 'details' => []];
|
||||
$rating = ['ort_kurzbz' => $raum->ort_kurzbz, 'score' => 100, 'details' => [],
|
||||
'raumtyp_kurzbz' => $raum->raumtyp_kurzbz, 'max_person' => $raum->max_person];
|
||||
$this->_rateLektor($rating, $raum, $lektor_davor_ort);
|
||||
$this->_rateGruppen($rating, $raum, $gruppen_davor_ort);
|
||||
$this->_rateGruppen($rating, $raum, $lehrverband_davor_ort);
|
||||
|
||||
Events::trigger('room_rating',
|
||||
function & () use (&$rating) {
|
||||
@@ -204,10 +453,7 @@ class RaumvorschlagLib
|
||||
if (empty($event->ort_kurzbz))
|
||||
continue;
|
||||
|
||||
if ($type === 'lektor')
|
||||
$event_uids = array_column($event->lektor, 'mitarbeiter_uid');
|
||||
else
|
||||
$event_uids = array_column($event->gruppe, 'gruppe_kurzbz');
|
||||
$event_uids = $this->_getIds($event, $type);
|
||||
|
||||
if (empty(array_intersect($event_uids, $uids)))
|
||||
continue;
|
||||
@@ -219,6 +465,20 @@ class RaumvorschlagLib
|
||||
return $kandidat;
|
||||
}
|
||||
|
||||
private function _getIds($event, $type)
|
||||
{
|
||||
$event_uids = array();
|
||||
|
||||
if ($type === 'lektor')
|
||||
$event_uids = array_column($event->lektor, 'mitarbeiter_uid');
|
||||
else if ($type === 'gruppe')
|
||||
$event_uids = array_column($event->gruppe, 'gruppe_kurzbz');
|
||||
else if ($type === 'lehrverband')
|
||||
$event_uids = array_column($event->gruppe, 'bezeichnung');
|
||||
|
||||
return $event_uids;
|
||||
}
|
||||
|
||||
private function _getRaumkandidaten($event)
|
||||
{
|
||||
$raumtyp = null;
|
||||
@@ -240,9 +500,19 @@ class RaumvorschlagLib
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'tbl_kalender.kalender_id = tbl_kalender_ort.kalender_id');
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.von <', $event->isoend);
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.bis >', $event->isostart);
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $event->kalender_id);
|
||||
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', ['deleted']);
|
||||
if (!is_null($event->kalender_id))
|
||||
{
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $event->kalender_id);
|
||||
}
|
||||
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', ['deleted', 'to_delete', 'to_delete_live', 'to_delete_preview', 'archived']);
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender_ort.ort_kurzbz IS NOT NULL', null, false);
|
||||
$this->_ci->KalenderModel->db->where(
|
||||
'NOT EXISTS (
|
||||
SELECT 1 FROM lehre.tbl_kalender nachfolger
|
||||
WHERE nachfolger.vorgaenger_kalender_id = tbl_kalender.kalender_id
|
||||
)', null, false
|
||||
);
|
||||
|
||||
$belegte = $this->_ci->KalenderModel->load();
|
||||
|
||||
$belegte_orte = hasData($belegte) ? array_column(getData($belegte), 'ort_kurzbz') : [];
|
||||
@@ -273,7 +543,7 @@ class RaumvorschlagLib
|
||||
|
||||
private function _getFreieRaeume($raumtyp, $belegte_orte)
|
||||
{
|
||||
$this->_ci->OrtModel->addSelect('ort_kurzbz, stockwerk, standort_id');
|
||||
$this->_ci->OrtModel->addSelect('ort_kurzbz, stockwerk, standort_id, max_person, raumtyp_kurzbz');
|
||||
$this->_ci->OrtModel->addJoin('public.tbl_ortraumtyp', 'ort_kurzbz');
|
||||
|
||||
if (!empty($raumtyp))
|
||||
@@ -290,11 +560,4 @@ class RaumvorschlagLib
|
||||
|
||||
return $this->_ci->OrtModel->load();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ class LectureCollisionCheck implements ICollisionCheck
|
||||
$this->_ci =& get_instance();
|
||||
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
|
||||
$this->_ci->load->model('ressource/Zeitsperre_model', 'ZeitsperreModel');
|
||||
$this->_ci->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel');
|
||||
$this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
|
||||
$this->_ci->load->library('PhrasesLib', array('ui'));
|
||||
|
||||
@@ -22,11 +23,17 @@ class LectureCollisionCheck implements ICollisionCheck
|
||||
|
||||
public function check($data)
|
||||
{
|
||||
if (!isset($data->von, $data->bis, $data->kalender_id)) return [];
|
||||
if (!isset($data->von, $data->bis)) return [];
|
||||
if (empty($data->kalender_id) && empty($data->lehreinheit_id) && empty($data->uids)) return [];
|
||||
|
||||
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
|
||||
|
||||
$uids = $this->_getUids($data->kalender_id);
|
||||
if (!empty($data->kalender_id))
|
||||
$uids = $this->_getUids($data->kalender_id);
|
||||
else if (!empty($data->lehreinheit_id))
|
||||
$uids = $this->_getUidsFromLehreinheit($data->lehreinheit_id);
|
||||
else
|
||||
$uids = $data->uids;
|
||||
|
||||
if (empty($uids)) return [];
|
||||
|
||||
@@ -58,9 +65,17 @@ class LectureCollisionCheck implements ICollisionCheck
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id != tbl_kalender.kalender_id', null, false);
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.von < tbl_kalender.bis', null, false);
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.bis > tbl_kalender.von', null, false);
|
||||
$this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete']);
|
||||
$this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
|
||||
$this->_ci->KalenderModel->db->where_not_in('current_lehreinheit_ma.mitarbeiter_uid', $kollisionsfreie_user);
|
||||
$this->_ci->KalenderModel->db->where_in('tbl_kalender.kalender_id', $kalender_ids);
|
||||
|
||||
$this->_ci->KalenderModel->db->group_start();
|
||||
$where_ids_chunks = array_chunk($kalender_ids,25);
|
||||
foreach($where_ids_chunks as $where_ids)
|
||||
{
|
||||
$this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
|
||||
}
|
||||
$this->_ci->KalenderModel->db->group_end();
|
||||
|
||||
$this->_ci->KalenderModel->db->where(
|
||||
'other_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)',
|
||||
null, false
|
||||
@@ -85,9 +100,17 @@ class LectureCollisionCheck implements ICollisionCheck
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id != tbl_kalender.kalender_id', null, false);
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.von < tbl_kalender.bis', null, false);
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.bis > tbl_kalender.von', null, false);
|
||||
$this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete']);
|
||||
$this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview']);
|
||||
$this->_ci->KalenderModel->db->where_not_in('current_lehreinheit_ma.mitarbeiter_uid', $kollisionsfreie_user);
|
||||
$this->_ci->KalenderModel->db->where_in('tbl_kalender.kalender_id', $kalender_ids);
|
||||
|
||||
$this->_ci->KalenderModel->db->group_start();
|
||||
$where_ids_chunks = array_chunk($kalender_ids,25);
|
||||
foreach($where_ids_chunks as $where_ids)
|
||||
{
|
||||
$this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
|
||||
}
|
||||
$this->_ci->KalenderModel->db->group_end();
|
||||
|
||||
$this->_ci->KalenderModel->db->where(
|
||||
'other_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)',
|
||||
null, false
|
||||
@@ -114,7 +137,13 @@ class LectureCollisionCheck implements ICollisionCheck
|
||||
$this->_ci->KalenderModel->db->where('(z.vondatum + COALESCE(vonstunde_z.beginn, \'00:00\'))::timestamp < tbl_kalender.bis', null, false);
|
||||
$this->_ci->KalenderModel->db->where('(z.bisdatum + COALESCE(bisstunde_z.ende, \'23:59\'))::timestamp > tbl_kalender.von', null, false);
|
||||
$this->_ci->KalenderModel->db->where_not_in('current_lehreinheit_ma.mitarbeiter_uid', $kollisionsfreie_user);
|
||||
$this->_ci->KalenderModel->db->where_in('tbl_kalender.kalender_id', $kalender_ids);
|
||||
$this->_ci->KalenderModel->db->group_start();
|
||||
$where_ids_chunks = array_chunk($kalender_ids,25);
|
||||
foreach($where_ids_chunks as $where_ids)
|
||||
{
|
||||
$this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
|
||||
}
|
||||
$this->_ci->KalenderModel->db->group_end();
|
||||
$result = $this->_ci->KalenderModel->load();
|
||||
|
||||
|
||||
@@ -159,6 +188,20 @@ class LectureCollisionCheck implements ICollisionCheck
|
||||
return array_unique(array_merge($mitarbeiter_uids, $event_teilnehmer));
|
||||
}
|
||||
|
||||
private function _getUidsFromLehreinheit($lehreinheit_id)
|
||||
{
|
||||
$kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER);
|
||||
|
||||
$result = $this->_ci->LehreinheitmitarbeiterModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id));
|
||||
|
||||
if (isError($result) || !hasData($result)) return [];
|
||||
|
||||
$uids = array_column(getData($result), 'mitarbeiter_uid');
|
||||
$uids = array_diff(array_filter($uids), $kollisionsfreie_user);
|
||||
|
||||
return array_values(array_unique($uids));
|
||||
}
|
||||
|
||||
private function _checkLehreinheit($uids, $data)
|
||||
{
|
||||
$kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER);
|
||||
@@ -170,8 +213,9 @@ class LectureCollisionCheck implements ICollisionCheck
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheitmitarbeiter', 'lehreinheit_id', 'LEFT');
|
||||
|
||||
$this->_ci->KalenderModel->db->where_in('mitarbeiter_uid', $uids);
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
|
||||
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete'));
|
||||
if (!empty($data->kalender_id))
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
|
||||
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
|
||||
$this->_ci->KalenderModel->db->where_not_in('mitarbeiter_uid', $kollisionsfreie_user);
|
||||
$this->_ci->KalenderModel->db->where(
|
||||
'tbl_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)',
|
||||
@@ -207,8 +251,9 @@ class LectureCollisionCheck implements ICollisionCheck
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_event_teilnehmer', 'tbl_kalender_event.kalender_id = tbl_kalender_event_teilnehmer.kalender_id', 'LEFT');
|
||||
|
||||
$this->_ci->KalenderModel->db->where_in('tbl_kalender_event_teilnehmer.uid', $uids);
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
|
||||
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete'));
|
||||
if (!empty($data->kalender_id))
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
|
||||
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
|
||||
$this->_ci->KalenderModel->db->where_not_in('uid', $kollisionsfreie_user);
|
||||
$this->_ci->KalenderModel->db->where(
|
||||
'tbl_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)',
|
||||
|
||||
@@ -20,7 +20,7 @@ class ResourcesCollisionCheck implements ICollisionCheck
|
||||
|
||||
public function check($data)
|
||||
{
|
||||
if (!isset($data->betriebsmittel_ids, $data->von, $data->bis, $data->kalender_id)) return [];
|
||||
if (!isset($data->betriebsmittel_ids, $data->von, $data->bis)) return [];
|
||||
|
||||
if (empty($data->betriebsmittel_ids)) return [];
|
||||
|
||||
@@ -31,9 +31,10 @@ class ResourcesCollisionCheck implements ICollisionCheck
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_betriebsmittel_kalender bk', 'bk.eindeutige_kalender_gruppen_id = tbl_kalender.eindeutige_kalender_gruppen_id');
|
||||
$this->_ci->KalenderModel->addJoin('wawi.tbl_betriebsmittel bm', 'bm.betriebsmittel_id = bk.betriebsmittel_id');
|
||||
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
|
||||
if (!empty($data->kalender_id))
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)', null, false);
|
||||
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete']);
|
||||
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview']);
|
||||
$this->_ci->KalenderModel->db->where_in('bk.betriebsmittel_id', $data->betriebsmittel_ids);
|
||||
|
||||
|
||||
@@ -66,8 +67,16 @@ class ResourcesCollisionCheck implements ICollisionCheck
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id != tbl_kalender.kalender_id', null, false);
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.von < tbl_kalender.bis', null, false);
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.bis > tbl_kalender.von', null, false);
|
||||
$this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete']);
|
||||
$this->_ci->KalenderModel->db->where_in('tbl_kalender.kalender_id', $kalender_ids);
|
||||
$this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview']);
|
||||
|
||||
$this->_ci->KalenderModel->db->group_start();
|
||||
$where_ids_chunks = array_chunk($kalender_ids,25);
|
||||
foreach($where_ids_chunks as $where_ids)
|
||||
{
|
||||
$this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
|
||||
}
|
||||
$this->_ci->KalenderModel->db->group_end();
|
||||
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)', null, false);
|
||||
|
||||
$result = $this->_ci->KalenderModel->load();
|
||||
|
||||
@@ -20,16 +20,17 @@ class RoomCollisionCheck implements ICollisionCheck
|
||||
|
||||
public function check($data)
|
||||
{
|
||||
if (!isset($data->ort_kurzbz, $data->von, $data->bis, $data->kalender_id) || isEmptyArray($data->ort_kurzbz)) return [];
|
||||
if (!isset($data->ort_kurzbz, $data->von, $data->bis) || isEmptyArray($data->ort_kurzbz)) return [];
|
||||
|
||||
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
|
||||
|
||||
$this->_ci->KalenderModel->addSelect('kalender_id, ort_kurzbz, von, bis');
|
||||
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'kalender_id');
|
||||
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
|
||||
if (!empty($data->kalender_id))
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
|
||||
$this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)', null, false);
|
||||
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete']);
|
||||
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
|
||||
|
||||
$this->_ci->KalenderModel->db->where_in('ort_kurzbz', $data->ort_kurzbz);
|
||||
$result = $this->_ci->KalenderModel->loadWhere(array(
|
||||
@@ -61,8 +62,16 @@ class RoomCollisionCheck implements ICollisionCheck
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id != tbl_kalender.kalender_id', null, false);
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.von < tbl_kalender.bis', null, false);
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.bis > tbl_kalender.von', null, false);
|
||||
$this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete']);
|
||||
$this->_ci->KalenderModel->db->where_in('tbl_kalender.kalender_id', $kalender_ids);
|
||||
$this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
|
||||
|
||||
$this->_ci->KalenderModel->db->group_start();
|
||||
$where_ids_chunks = array_chunk($kalender_ids,25);
|
||||
foreach($where_ids_chunks as $where_ids)
|
||||
{
|
||||
$this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
|
||||
}
|
||||
$this->_ci->KalenderModel->db->group_end();
|
||||
|
||||
$this->_ci->KalenderModel->db->where('other_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)', null, false);
|
||||
|
||||
$result = $this->_ci->KalenderModel->load();
|
||||
|
||||
@@ -19,7 +19,8 @@ class StudentCollisionCheck implements ICollisionCheck
|
||||
|
||||
public function check($data)
|
||||
{
|
||||
if (!isset($data->von, $data->bis, $data->kalender_id)) return [];
|
||||
if (!isset($data->von, $data->bis)) return [];
|
||||
if (!isset($data->kalender_id) && !isset($data->lehreinheit_id)) return [];
|
||||
|
||||
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
|
||||
if ($this->_ci->variablelib->getVar('kollision_student') !== 'true') return [];
|
||||
@@ -30,7 +31,9 @@ class StudentCollisionCheck implements ICollisionCheck
|
||||
|
||||
$dbModel = new DB_Model();
|
||||
|
||||
$qry1 = "
|
||||
if (isset($data->kalender_id))
|
||||
{
|
||||
$qry1 = "
|
||||
SELECT DISTINCT tbl_benutzergruppe.uid
|
||||
FROM lehre.tbl_kalender
|
||||
JOIN lehre.tbl_kalender_lehreinheit USING(kalender_id)
|
||||
@@ -60,13 +63,48 @@ class StudentCollisionCheck implements ICollisionCheck
|
||||
AND (tbl_lehreinheitgruppe.gruppe = tbl_studentlehrverband.gruppe OR tbl_lehreinheitgruppe.gruppe IS NULL OR btrim(tbl_lehreinheitgruppe.gruppe::text) = '' OR tbl_studentlehrverband.gruppe IS NULL)
|
||||
WHERE tbl_kalender.kalender_id = ?
|
||||
AND tbl_studentlehrverband.student_uid NOT IN ($placeholders)
|
||||
";
|
||||
|
||||
";
|
||||
$qry_1_param = $data->kalender_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$qry1 = "
|
||||
SELECT DISTINCT tbl_benutzergruppe.uid
|
||||
FROM lehre.tbl_lehreinheit
|
||||
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
|
||||
JOIN public.tbl_gruppe
|
||||
ON tbl_gruppe.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
|
||||
AND tbl_gruppe.semester = tbl_lehreinheitgruppe.semester
|
||||
AND tbl_gruppe.gruppe_kurzbz = tbl_lehreinheitgruppe.gruppe_kurzbz
|
||||
JOIN public.tbl_benutzergruppe ON tbl_benutzergruppe.gruppe_kurzbz = tbl_gruppe.gruppe_kurzbz
|
||||
AND tbl_benutzergruppe.studiensemester_kurzbz = tbl_lehreinheit.studiensemester_kurzbz
|
||||
|
||||
WHERE tbl_lehreinheit.lehreinheit_id = ?
|
||||
AND tbl_benutzergruppe.uid NOT IN ($placeholders)
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT DISTINCT tbl_studentlehrverband.student_uid AS uid
|
||||
FROM lehre.tbl_lehreinheit
|
||||
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
|
||||
JOIN public.tbl_studentlehrverband
|
||||
ON tbl_studentlehrverband.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
|
||||
AND tbl_studentlehrverband.semester = tbl_lehreinheitgruppe.semester
|
||||
AND tbl_studentlehrverband.studiensemester_kurzbz = tbl_lehreinheit.studiensemester_kurzbz
|
||||
AND (tbl_lehreinheitgruppe.verband = tbl_studentlehrverband.verband OR tbl_lehreinheitgruppe.verband IS NULL OR btrim(tbl_lehreinheitgruppe.verband::text) = '' OR tbl_studentlehrverband.verband IS NULL)
|
||||
AND (tbl_lehreinheitgruppe.gruppe = tbl_studentlehrverband.gruppe OR tbl_lehreinheitgruppe.gruppe IS NULL OR btrim(tbl_lehreinheitgruppe.gruppe::text) = '' OR tbl_studentlehrverband.gruppe IS NULL)
|
||||
WHERE tbl_lehreinheit.lehreinheit_id = ?
|
||||
AND tbl_studentlehrverband.student_uid NOT IN ($placeholders)
|
||||
";
|
||||
|
||||
$qry_1_param = $data->lehreinheit_id;
|
||||
}
|
||||
|
||||
$result1 = $dbModel->execReadOnlyQuery($qry1, array_merge(
|
||||
[$data->kalender_id],
|
||||
[$qry_1_param],
|
||||
$kollisionsfreie_user,
|
||||
[$data->kalender_id],
|
||||
[$qry_1_param],
|
||||
$kollisionsfreie_user
|
||||
));
|
||||
|
||||
@@ -74,6 +112,9 @@ class StudentCollisionCheck implements ICollisionCheck
|
||||
|
||||
$curUids = array_flip(array_column(getData($result1), 'uid'));
|
||||
|
||||
$exclude_kalender = isset($data->kalender_id) ? "AND tbl_kalender.kalender_id != ?" : "";
|
||||
$exclude_kalender_param = isset($data->kalender_id) ? [$data->kalender_id] : [];
|
||||
|
||||
$qry2 = "
|
||||
SELECT DISTINCT tbl_kalender.kalender_id, tbl_kalender.von, tbl_kalender.bis, tbl_benutzergruppe.uid
|
||||
FROM lehre.tbl_kalender
|
||||
@@ -88,8 +129,8 @@ class StudentCollisionCheck implements ICollisionCheck
|
||||
AND tbl_benutzergruppe.studiensemester_kurzbz = tbl_lehreinheit.studiensemester_kurzbz
|
||||
WHERE tbl_kalender.von < ?
|
||||
AND tbl_kalender.bis > ?
|
||||
AND tbl_kalender.kalender_id != ?
|
||||
AND tbl_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
|
||||
$exclude_kalender
|
||||
AND tbl_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
|
||||
AND tbl_benutzergruppe.uid NOT IN ($placeholders)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM lehre.tbl_kalender vorgaenger
|
||||
@@ -97,7 +138,7 @@ class StudentCollisionCheck implements ICollisionCheck
|
||||
)
|
||||
|
||||
UNION ALL
|
||||
|
||||
|
||||
SELECT DISTINCT tbl_kalender.kalender_id, tbl_kalender.von, tbl_kalender.bis, tbl_studentlehrverband.student_uid AS uid
|
||||
FROM lehre.tbl_kalender
|
||||
JOIN lehre.tbl_kalender_lehreinheit ON tbl_kalender_lehreinheit.kalender_id = tbl_kalender.kalender_id
|
||||
@@ -111,8 +152,8 @@ class StudentCollisionCheck implements ICollisionCheck
|
||||
AND (tbl_lehreinheitgruppe.gruppe = tbl_studentlehrverband.gruppe OR tbl_lehreinheitgruppe.gruppe IS NULL OR btrim(tbl_lehreinheitgruppe.gruppe::text) = '' OR tbl_studentlehrverband.gruppe IS NULL)
|
||||
WHERE tbl_kalender.von < ?
|
||||
AND tbl_kalender.bis > ?
|
||||
AND tbl_kalender.kalender_id != ?
|
||||
AND tbl_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
|
||||
$exclude_kalender
|
||||
AND tbl_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
|
||||
AND tbl_studentlehrverband.student_uid NOT IN ($placeholders)
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM lehre.tbl_kalender vorgaenger
|
||||
@@ -121,10 +162,8 @@ class StudentCollisionCheck implements ICollisionCheck
|
||||
";
|
||||
|
||||
$result2 = $dbModel->execReadOnlyQuery($qry2, array_merge(
|
||||
[$data->bis, $data->von, $data->kalender_id],
|
||||
$kollisionsfreie_user,
|
||||
[$data->bis, $data->von, $data->kalender_id],
|
||||
$kollisionsfreie_user
|
||||
[$data->bis, $data->von], $exclude_kalender_param, $kollisionsfreie_user,
|
||||
[$data->bis, $data->von], $exclude_kalender_param, $kollisionsfreie_user
|
||||
));
|
||||
|
||||
if (isError($result2) || !hasData($result2)) return [];
|
||||
@@ -175,7 +214,7 @@ class StudentCollisionCheck implements ICollisionCheck
|
||||
ON other_kalender.kalender_id != current_kalender.kalender_id
|
||||
AND other_kalender.von < current_kalender.bis
|
||||
AND other_kalender.bis > current_kalender.von
|
||||
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
|
||||
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM lehre.tbl_kalender vorgaenger
|
||||
WHERE vorgaenger.vorgaenger_kalender_id = other_kalender.kalender_id
|
||||
@@ -213,7 +252,7 @@ class StudentCollisionCheck implements ICollisionCheck
|
||||
ON other_kalender.kalender_id != current_kalender.kalender_id
|
||||
AND other_kalender.von < current_kalender.bis
|
||||
AND other_kalender.bis > current_kalender.von
|
||||
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
|
||||
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM lehre.tbl_kalender vorgaenger
|
||||
WHERE vorgaenger.vorgaenger_kalender_id = other_kalender.kalender_id
|
||||
|
||||
@@ -21,18 +21,58 @@ class VerbandCollisionCheck implements ICollisionCheck
|
||||
|
||||
public function check($data)
|
||||
{
|
||||
if (!isset($data->von, $data->bis, $data->kalender_id)) return [];
|
||||
if (!isset($data->von, $data->bis)) return [];
|
||||
if (!isset($data->kalender_id) && !isset($data->lehreinheit_id)) return [];
|
||||
|
||||
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
|
||||
|
||||
$kollision_student = $this->_ci->variablelib->getVar('kollision_student') === 'false';
|
||||
$kollision_reservierung = $this->_ci->variablelib->getVar('ignore_reservierung') === 'false';
|
||||
|
||||
if (!isset($data->kalender_id)) $kollision_reservierung = false;
|
||||
|
||||
if (!$kollision_student && !$kollision_reservierung) return [];
|
||||
|
||||
$dbModel = new DB_Model();
|
||||
$collisions = [];
|
||||
|
||||
$group_matching_qry = "
|
||||
(
|
||||
(
|
||||
current_lehreinheitguppe.gruppe_kurzbz IS NULL
|
||||
AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
|
||||
AND (
|
||||
current_lehreinheitguppe.verband IS NULL
|
||||
OR (
|
||||
current_lehreinheitguppe.verband = other_lehreinheitguppe.verband
|
||||
AND (current_lehreinheitguppe.gruppe IS NULL OR other_lehreinheitguppe.gruppe IS NULL OR current_lehreinheitguppe.gruppe = other_lehreinheitguppe.gruppe)
|
||||
)
|
||||
)
|
||||
)
|
||||
OR
|
||||
(
|
||||
current_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
|
||||
AND other_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
|
||||
AND current_gruppe.direktinskription IS NOT TRUE
|
||||
AND other_gruppe.direktinskription IS NOT TRUE
|
||||
)
|
||||
OR
|
||||
(
|
||||
(
|
||||
current_lehreinheitguppe.gruppe_kurzbz IS NULL
|
||||
AND other_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
|
||||
AND other_gruppe.direktinskription IS NOT TRUE
|
||||
)
|
||||
OR
|
||||
(
|
||||
current_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
|
||||
AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
|
||||
AND current_gruppe.direktinskription IS NOT TRUE
|
||||
)
|
||||
)
|
||||
)
|
||||
";
|
||||
|
||||
if ($kollision_student)
|
||||
{
|
||||
$union_event = "";
|
||||
@@ -47,100 +87,111 @@ class VerbandCollisionCheck implements ICollisionCheck
|
||||
";
|
||||
}
|
||||
|
||||
$sql_gruppen = "
|
||||
SELECT
|
||||
other_kalender.von,
|
||||
other_kalender.bis,
|
||||
COALESCE(
|
||||
other_lehreinheitguppe.gruppe_kurzbz,
|
||||
UPPER(stg.typ::text || stg.kurzbz::text) || '-' || other_lehreinheitguppe.semester ||
|
||||
COALESCE(other_lehreinheitguppe.verband::text, '') ||
|
||||
COALESCE(other_lehreinheitguppe.gruppe::text, '')
|
||||
) AS gruppenname
|
||||
FROM lehre.tbl_kalender current_kalender
|
||||
$other_lehreinheitgruppe_subquery = "
|
||||
SELECT tbl_lehreinheitgruppe.studiengang_kz, tbl_lehreinheitgruppe.semester, tbl_lehreinheitgruppe.verband, tbl_lehreinheitgruppe.gruppe,
|
||||
tbl_lehreinheitgruppe.gruppe_kurzbz, tbl_kalender_lehreinheit.kalender_id
|
||||
FROM lehre.tbl_kalender_lehreinheit
|
||||
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
|
||||
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
|
||||
". $union_event ."
|
||||
";
|
||||
|
||||
JOIN (
|
||||
SELECT tbl_lehreinheitgruppe.studiengang_kz, tbl_lehreinheitgruppe.semester, tbl_lehreinheitgruppe.verband, tbl_lehreinheitgruppe.gruppe,
|
||||
tbl_lehreinheitgruppe.gruppe_kurzbz, tbl_kalender_lehreinheit.kalender_id
|
||||
FROM lehre.tbl_kalender_lehreinheit
|
||||
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
|
||||
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
|
||||
". $union_event ."
|
||||
) current_lehreinheitguppe ON current_lehreinheitguppe.kalender_id = current_kalender.kalender_id
|
||||
|
||||
LEFT JOIN public.tbl_gruppe current_gruppe
|
||||
ON current_gruppe.gruppe_kurzbz = current_lehreinheitguppe.gruppe_kurzbz
|
||||
|
||||
JOIN lehre.tbl_kalender other_kalender
|
||||
ON other_kalender.kalender_id != current_kalender.kalender_id
|
||||
AND other_kalender.von < ?
|
||||
AND other_kalender.bis > ?
|
||||
|
||||
JOIN (
|
||||
SELECT tbl_lehreinheitgruppe.studiengang_kz, tbl_lehreinheitgruppe.semester, tbl_lehreinheitgruppe.verband, tbl_lehreinheitgruppe.gruppe,
|
||||
tbl_lehreinheitgruppe.gruppe_kurzbz, tbl_kalender_lehreinheit.kalender_id
|
||||
FROM lehre.tbl_kalender_lehreinheit
|
||||
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
|
||||
JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
|
||||
". $union_event ."
|
||||
) other_lehreinheitguppe ON other_lehreinheitguppe.kalender_id = other_kalender.kalender_id
|
||||
|
||||
LEFT JOIN public.tbl_gruppe other_gruppe
|
||||
ON other_gruppe.gruppe_kurzbz = other_lehreinheitguppe.gruppe_kurzbz
|
||||
|
||||
LEFT JOIN public.tbl_studiengang stg
|
||||
ON stg.studiengang_kz = other_lehreinheitguppe.studiengang_kz
|
||||
|
||||
WHERE current_kalender.kalender_id = ?
|
||||
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
|
||||
AND current_lehreinheitguppe.studiengang_kz = other_lehreinheitguppe.studiengang_kz
|
||||
AND current_lehreinheitguppe.semester = other_lehreinheitguppe.semester
|
||||
AND (
|
||||
(
|
||||
current_lehreinheitguppe.gruppe_kurzbz IS NULL
|
||||
AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
|
||||
AND (
|
||||
current_lehreinheitguppe.verband IS NULL
|
||||
OR (
|
||||
current_lehreinheitguppe.verband = other_lehreinheitguppe.verband
|
||||
AND (current_lehreinheitguppe.gruppe IS NULL OR other_lehreinheitguppe.gruppe IS NULL OR current_lehreinheitguppe.gruppe = other_lehreinheitguppe.gruppe)
|
||||
)
|
||||
)
|
||||
if (isset($data->kalender_id))
|
||||
{
|
||||
$sql_gruppen = "
|
||||
SELECT
|
||||
other_kalender.von,
|
||||
other_kalender.bis,
|
||||
COALESCE(
|
||||
other_lehreinheitguppe.gruppe_kurzbz,
|
||||
UPPER(stg.typ::text || stg.kurzbz::text) || '-' || other_lehreinheitguppe.semester ||
|
||||
COALESCE(other_lehreinheitguppe.verband::text, '') ||
|
||||
COALESCE(other_lehreinheitguppe.gruppe::text, '')
|
||||
) AS gruppenname
|
||||
FROM lehre.tbl_kalender current_kalender
|
||||
|
||||
JOIN (
|
||||
". $other_lehreinheitgruppe_subquery ."
|
||||
) current_lehreinheitguppe ON current_lehreinheitguppe.kalender_id = current_kalender.kalender_id
|
||||
|
||||
LEFT JOIN public.tbl_gruppe current_gruppe
|
||||
ON current_gruppe.gruppe_kurzbz = current_lehreinheitguppe.gruppe_kurzbz
|
||||
|
||||
JOIN lehre.tbl_kalender other_kalender
|
||||
ON other_kalender.kalender_id != current_kalender.kalender_id
|
||||
AND other_kalender.von < ?
|
||||
AND other_kalender.bis > ?
|
||||
|
||||
JOIN (
|
||||
". $other_lehreinheitgruppe_subquery ."
|
||||
) other_lehreinheitguppe ON other_lehreinheitguppe.kalender_id = other_kalender.kalender_id
|
||||
|
||||
LEFT JOIN public.tbl_gruppe other_gruppe
|
||||
ON other_gruppe.gruppe_kurzbz = other_lehreinheitguppe.gruppe_kurzbz
|
||||
|
||||
LEFT JOIN public.tbl_studiengang stg
|
||||
ON stg.studiengang_kz = other_lehreinheitguppe.studiengang_kz
|
||||
|
||||
WHERE current_kalender.kalender_id = ?
|
||||
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
|
||||
AND current_lehreinheitguppe.studiengang_kz = other_lehreinheitguppe.studiengang_kz
|
||||
AND current_lehreinheitguppe.semester = other_lehreinheitguppe.semester
|
||||
AND ". $group_matching_qry ."
|
||||
AND other_kalender.kalender_id NOT IN (
|
||||
SELECT vorgaenger_kalender_id
|
||||
FROM lehre.tbl_kalender
|
||||
WHERE vorgaenger_kalender_id IS NOT NULL
|
||||
)
|
||||
OR
|
||||
(
|
||||
current_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
|
||||
AND other_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
|
||||
AND current_gruppe.direktinskription IS NOT TRUE
|
||||
AND other_gruppe.direktinskription IS NOT TRUE
|
||||
)
|
||||
OR
|
||||
(
|
||||
(
|
||||
current_lehreinheitguppe.gruppe_kurzbz IS NULL
|
||||
AND other_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
|
||||
AND other_gruppe.direktinskription IS NOT TRUE
|
||||
)
|
||||
OR
|
||||
(
|
||||
current_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
|
||||
AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
|
||||
AND current_gruppe.direktinskription IS NOT TRUE
|
||||
)
|
||||
)
|
||||
)
|
||||
AND other_kalender.kalender_id NOT IN (
|
||||
SELECT vorgaenger_kalender_id
|
||||
FROM lehre.tbl_kalender
|
||||
WHERE vorgaenger_kalender_id IS NOT NULL
|
||||
)
|
||||
";
|
||||
";
|
||||
|
||||
$result = $dbModel->execReadOnlyQuery($sql_gruppen, [
|
||||
$data->bis,
|
||||
$data->von,
|
||||
$data->kalender_id,
|
||||
]);
|
||||
$params = [$data->bis, $data->von, $data->kalender_id];
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql_gruppen = "
|
||||
SELECT
|
||||
other_kalender.von,
|
||||
other_kalender.bis,
|
||||
COALESCE(
|
||||
other_lehreinheitguppe.gruppe_kurzbz,
|
||||
UPPER(stg.typ::text || stg.kurzbz::text) || '-' || other_lehreinheitguppe.semester ||
|
||||
COALESCE(other_lehreinheitguppe.verband::text, '') ||
|
||||
COALESCE(other_lehreinheitguppe.gruppe::text, '')
|
||||
) AS gruppenname
|
||||
FROM lehre.tbl_lehreinheitgruppe current_lehreinheitguppe
|
||||
LEFT JOIN public.tbl_gruppe current_gruppe
|
||||
ON current_gruppe.gruppe_kurzbz = current_lehreinheitguppe.gruppe_kurzbz
|
||||
|
||||
JOIN lehre.tbl_kalender other_kalender
|
||||
ON other_kalender.von < ?
|
||||
AND other_kalender.bis > ?
|
||||
|
||||
JOIN (
|
||||
". $other_lehreinheitgruppe_subquery ."
|
||||
) other_lehreinheitguppe ON other_lehreinheitguppe.kalender_id = other_kalender.kalender_id
|
||||
|
||||
LEFT JOIN public.tbl_gruppe other_gruppe
|
||||
ON other_gruppe.gruppe_kurzbz = other_lehreinheitguppe.gruppe_kurzbz
|
||||
|
||||
LEFT JOIN public.tbl_studiengang stg
|
||||
ON stg.studiengang_kz = other_lehreinheitguppe.studiengang_kz
|
||||
|
||||
WHERE current_lehreinheitguppe.lehreinheit_id = ?
|
||||
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
|
||||
AND current_lehreinheitguppe.studiengang_kz = other_lehreinheitguppe.studiengang_kz
|
||||
AND current_lehreinheitguppe.semester = other_lehreinheitguppe.semester
|
||||
AND ". $group_matching_qry ."
|
||||
AND other_kalender.kalender_id NOT IN (
|
||||
SELECT vorgaenger_kalender_id
|
||||
FROM lehre.tbl_kalender
|
||||
WHERE vorgaenger_kalender_id IS NOT NULL
|
||||
)
|
||||
";
|
||||
|
||||
$params = [$data->bis, $data->von, $data->lehreinheit_id];
|
||||
}
|
||||
|
||||
$result = $dbModel->execReadOnlyQuery($sql_gruppen, $params);
|
||||
|
||||
if (!isError($result) && hasData($result))
|
||||
{
|
||||
@@ -187,7 +238,7 @@ class VerbandCollisionCheck implements ICollisionCheck
|
||||
|
||||
WHERE current_event_teilnehmer.kalender_id = ?
|
||||
AND current_event_teilnehmer.rolle_kurzbz = 'teilnehmer'
|
||||
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
|
||||
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
|
||||
AND current_event_teilnehmer.studiengang_kz = other_event_teilnehmer.studiengang_kz
|
||||
AND current_event_teilnehmer.semester = other_event_teilnehmer.semester
|
||||
AND (
|
||||
@@ -301,7 +352,7 @@ class VerbandCollisionCheck implements ICollisionCheck
|
||||
ON other_gruppe.gruppe_kurzbz = other_lehreinheitguppe.gruppe_kurzbz
|
||||
|
||||
WHERE current_kalender.kalender_id IN ({$placeholders})
|
||||
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
|
||||
AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
|
||||
AND current_lehreinheitguppe.studiengang_kz = other_lehreinheitguppe.studiengang_kz
|
||||
AND current_lehreinheitguppe.semester = other_lehreinheitguppe.semester
|
||||
AND (
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
class Kalendersyncstatus_model extends DB_Model
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dbTable = 'lehre.tbl_kalender_syncstatus';
|
||||
$this->pk = 'kalender_syncstatus_id';
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,14 @@
|
||||
'vue3' => true,
|
||||
'primevue3' => true,
|
||||
'tabulator5' => true,
|
||||
'filtercomponent' => true,
|
||||
'navigationcomponent' => true,
|
||||
'vuedatepicker11' => true,
|
||||
'tags' => true,
|
||||
'phrases' => array(
|
||||
'global',
|
||||
'ui',
|
||||
'notiz',
|
||||
'lehre'
|
||||
),
|
||||
'customCSSs' => [
|
||||
'public/css/components/vue-datepicker.css',
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
@import './components/Notiz.css';
|
||||
@import './components/Messages.css';
|
||||
@import './components/AppMenu.css';
|
||||
@import './components/horizontalsplit.css';
|
||||
|
||||
|
||||
html {
|
||||
font-size: .875em;
|
||||
|
||||
+34
-5
@@ -110,15 +110,23 @@ body {
|
||||
background-color: var(--event-bg);
|
||||
}
|
||||
|
||||
.parkingevent {
|
||||
.course-parker {
|
||||
position: relative;
|
||||
border: 1px dashed !important;
|
||||
border-color: #AAAAAA;
|
||||
padding: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
margin-left: 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
margin: 0.5rem;
|
||||
background-color: var(--event-bg);
|
||||
color: var(--event-color, var(--fhc-calendar-color-event, #000));
|
||||
}
|
||||
|
||||
.unpark-btn {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
padding: 0 4px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
}
|
||||
:root{
|
||||
--fhc-calendar-pane-height: calc(100vh - 120px);
|
||||
}
|
||||
@@ -171,6 +179,21 @@ body {
|
||||
}
|
||||
|
||||
|
||||
.bg-raumvorschlag-slot {
|
||||
opacity: .70;
|
||||
}
|
||||
|
||||
.bg-raumvorschlag-slot.rating-good {
|
||||
background-color: var(--bs-success);
|
||||
}
|
||||
.bg-raumvorschlag-slot.rating-mid {
|
||||
background-color: var(--bs-warning);
|
||||
}
|
||||
.bg-raumvorschlag-slot.rating-bad {
|
||||
background-color: var(--bs-danger);
|
||||
}
|
||||
|
||||
|
||||
.wish-w--2 {
|
||||
background-color: #FF2200;
|
||||
}
|
||||
@@ -185,3 +208,9 @@ body {
|
||||
}
|
||||
|
||||
|
||||
.room-option {
|
||||
display: grid;
|
||||
grid-template-columns: 20px minmax(80px, 110px) minmax(100px, 1fr) auto 20px 50px;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -68,9 +68,16 @@
|
||||
/* Grid */
|
||||
.fhc-calendar-base-grid {
|
||||
--fhc-calendar-axis-collapsible: .2fr;
|
||||
--fhc-calendar-axis-collapsible-manual: .1fr;
|
||||
|
||||
background-color: var(--fhc-calendar-bg-gap);
|
||||
grid-gap: var(--fhc-calendar-gap-header, calc(var(--fhc-calendar-gap, 1px) * 2));
|
||||
}
|
||||
|
||||
.fhc-calendar-base-grid-line-collapsed {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.fhc-calendar-base-grid .grid-header {
|
||||
background-color: var(--fhc-calendar-bg-header-gap, var(--fhc-calendar-bg-gap));
|
||||
}
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
export default {
|
||||
search(query) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/tempus/coursepicker/search',
|
||||
params: { query }
|
||||
};
|
||||
},
|
||||
getByStg(studiengaenge, studiensemester_kurzbz) {
|
||||
getCourses(filter, studiensemester_kurzbz) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/tempus/coursepicker/getByStg',
|
||||
params: { studiengaenge, studiensemester_kurzbz }
|
||||
url: 'api/frontend/v1/tempus/coursepicker/getCourses',
|
||||
params: { ...filter, studiensemester_kurzbz }
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@@ -8,6 +8,14 @@ export default {
|
||||
params: { ...filter, start_date, end_date }
|
||||
};
|
||||
},
|
||||
getRaumvorschlagSlots(lehreinheit_id, start_date, end_date)
|
||||
{
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/tempus/Kalender/getRaumvorschlagSlots',
|
||||
params: { lehreinheit_id, start_date, end_date }
|
||||
};
|
||||
},
|
||||
getPlanLecturer(start_date, end_date)
|
||||
{
|
||||
return {
|
||||
|
||||
@@ -48,11 +48,11 @@ export default {
|
||||
url: '/api/frontend/v1/tempus/Reservierung/getRollen',
|
||||
};
|
||||
},
|
||||
addReservierung(titel, beschreibung, ort_kurzbz, start_date, end_date, teilnehmer, specialFinalGroups, specialGroups, groups) {
|
||||
addReservierung(titel, beschreibung, orte, start_date, end_date, teilnehmer, specialFinalGroups, specialGroups, groups) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/tempus/Reservierung/addReservierung',
|
||||
params: { titel, beschreibung, ort_kurzbz, start_date, end_date, teilnehmer, specialFinalGroups, specialGroups, groups}
|
||||
params: { titel, beschreibung, orte, start_date, end_date, teilnehmer, specialFinalGroups, specialGroups, groups}
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright (C) 2026 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
getSyncs(studiensemester_kurzbz) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/tempus/KalenderSync/getSyncs',
|
||||
params: { studiensemester_kurzbz }
|
||||
};
|
||||
},
|
||||
loadSync(kalender_syncstatus_id) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/tempus/KalenderSync/loadSync',
|
||||
params: { kalender_syncstatus_id }
|
||||
};
|
||||
},
|
||||
getSyncStatus() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/tempus/KalenderSync/getSyncStatus',
|
||||
};
|
||||
},
|
||||
add(formData) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/tempus/KalenderSync/add',
|
||||
params: { formData }
|
||||
};
|
||||
},
|
||||
delete(kalender_syncstatus_id) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/tempus/KalenderSync/delete',
|
||||
params: { kalender_syncstatus_id }
|
||||
};
|
||||
},
|
||||
start(formData) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/tempus/KalenderSync/start',
|
||||
params: { formData }
|
||||
};
|
||||
},
|
||||
updateSync(formData) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/tempus/KalenderSync/updateSync',
|
||||
params: { formData }
|
||||
};
|
||||
},
|
||||
getStudienplan(oe_kurzbz, studiensemester_kurzbz, ausbildungssemester) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: 'api/frontend/v1/tempus/KalenderSync/getStudienplan',
|
||||
params: { oe_kurzbz, studiensemester_kurzbz, ausbildungssemester }
|
||||
};
|
||||
},
|
||||
|
||||
getMaxSemester(studiengang_kzs) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: 'api/frontend/v1/stv/status/getMaxSemester/',
|
||||
params: { studiengang_kzs }
|
||||
};
|
||||
},
|
||||
|
||||
};
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import FhcTempus from "../components/Tempus/Tempus.js";
|
||||
import FhcTempusSync from "../components/Tempus/TempusSync.js";
|
||||
|
||||
import Phrasen from "../plugins/Phrasen.js";
|
||||
import {capitalize} from "../helpers/StringHelpers.js";
|
||||
@@ -27,6 +28,7 @@ const router = VueRouter.createRouter({
|
||||
history: VueRouter.createWebHistory(),
|
||||
routes: [
|
||||
{ path: `/${ciPath}/Tempus`, component: FhcTempus },
|
||||
{ path: `/${ciPath}/Tempus/sync`, component: FhcTempusSync },
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
@@ -137,12 +137,14 @@ export default {
|
||||
"update:date",
|
||||
"update:mode",
|
||||
"update:range",
|
||||
"update:date-range",
|
||||
"drop"
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
internalView: null,
|
||||
internalDate: null,
|
||||
pickedRangeEnd: null,
|
||||
modalEvent: null
|
||||
};
|
||||
},
|
||||
@@ -272,6 +274,10 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
handleDateRange({ start, end }) {
|
||||
this.pickedRangeEnd = end;
|
||||
this.$emit('update:date-range', { start, end });
|
||||
},
|
||||
showEventModal(eventObj) {
|
||||
this.modalEvent = eventObj;
|
||||
this.$refs.modal.show();
|
||||
@@ -300,6 +306,7 @@ export default {
|
||||
class="card-header"
|
||||
v-model:date="cDate"
|
||||
v-model:mode="cMode"
|
||||
@update:date-range="handleDateRange"
|
||||
@prev="clickPrev"
|
||||
@next="clickNext"
|
||||
@click:mode="$emit('click:mode', $event)"
|
||||
@@ -316,6 +323,7 @@ export default {
|
||||
:is="modes ? modes[cMode] : null || 'div'"
|
||||
ref="mode"
|
||||
v-model:current-date="cDate"
|
||||
:range-end="pickedRangeEnd"
|
||||
@update:range="$emit('update:range', $event)"
|
||||
@request-modal-open="showEventModal"
|
||||
@request-modal-close="hideEventModal"
|
||||
|
||||
@@ -61,7 +61,11 @@ export default {
|
||||
flipAxis: Boolean,
|
||||
allDayEvents: Boolean,
|
||||
axisMainCollapsible: Boolean,
|
||||
snapToGrid: Boolean
|
||||
snapToGrid: Boolean,
|
||||
dayVisibility: {
|
||||
type: Array,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -160,7 +164,17 @@ export default {
|
||||
hasValidEvents() {
|
||||
return this.events.find(e => e.length);
|
||||
},
|
||||
styleGridCols() {
|
||||
styleGridCols()
|
||||
{
|
||||
if (this.dayVisibility)
|
||||
{
|
||||
let anyVisible = this.dayVisibility.some(day => day);
|
||||
if (anyVisible)
|
||||
{
|
||||
return this.axisMain.map((day, i) => this.isDayCollapsed(i) ? 'var(--fhc-calendar-axis-collapsible-manual, 0.1fr)' : '1fr').join(' ');
|
||||
}
|
||||
}
|
||||
|
||||
let cols = 'repeat(' + this.axisMain.length + ', 1fr)';
|
||||
if (this.axisMainCollapsible) {
|
||||
if (this.hasValidEvents)
|
||||
@@ -479,6 +493,16 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
isDayCollapsed(index)
|
||||
{
|
||||
if (this.dayVisibility)
|
||||
{
|
||||
let anyVisible = this.dayVisibility.some(day => day);
|
||||
if (anyVisible)
|
||||
return !this.dayVisibility[index];
|
||||
}
|
||||
return this.axisMainCollapsible && this.hasValidEvents && !this.events[index].length;
|
||||
}
|
||||
},
|
||||
setup()
|
||||
{
|
||||
@@ -504,7 +528,7 @@ export default {
|
||||
v-for="(date, index) in axisMain"
|
||||
:key="index"
|
||||
class="main-header"
|
||||
:class="{'collapsed-header': axisMainCollapsible && hasValidEvents && !events[index].length}"
|
||||
:class="{'collapsed-header': isDayCollapsed(index)}"
|
||||
:style="'grid-' + axisCol + ':' + (2+index)"
|
||||
>
|
||||
<slot name="main-header" v-bind="{ index, date }" />
|
||||
@@ -592,6 +616,7 @@ export default {
|
||||
:date="date"
|
||||
:events="eventsNormal[index]"
|
||||
:backgrounds="backgrounds[index]"
|
||||
:class="{ 'fhc-calendar-base-grid-line-collapsed': isDayCollapsed(index) }"
|
||||
style="position:relative"
|
||||
@resize-start="handleResizeStart"
|
||||
:style="'grid-' + axisRow + ':1/-1;grid-' + axisCol + ':' + (1+index)"
|
||||
|
||||
@@ -9,6 +9,10 @@ export default {
|
||||
event: { type: Object, required: true },
|
||||
parked: Boolean
|
||||
},
|
||||
emits: [
|
||||
'select-kw',
|
||||
'unpark'
|
||||
],
|
||||
computed: {
|
||||
dragKalenderCollection() {
|
||||
return this.event
|
||||
@@ -16,21 +20,48 @@ export default {
|
||||
topicString() {
|
||||
return Array.isArray(this.event.orig.topic) ? this.event.orig.topic.join(', ') : this.event.orig.topic;
|
||||
},
|
||||
datum() {
|
||||
return luxon.DateTime.fromISO(this.event.orig.datum).toFormat('dd.MM.yyyy')
|
||||
},
|
||||
kw() {
|
||||
return luxon.DateTime.fromISO(this.event.orig.datum).startOf('week', { useLocaleWeeks: true }).localWeekNumber
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
eventStyle(event) {
|
||||
if (!event.farbe)
|
||||
return undefined;
|
||||
return '--event-bg:#' + event.farbe;
|
||||
},
|
||||
jumpToKw()
|
||||
{
|
||||
this.$emit('select-kw', this.kw);
|
||||
},
|
||||
unpark(evt)
|
||||
{
|
||||
this.$emit('unpark', this.event);
|
||||
}
|
||||
},
|
||||
|
||||
template: `
|
||||
<div
|
||||
class="fhc-calendar-base-grid-line-event event"
|
||||
class="course-parker event"
|
||||
v-draggable:move.noimage="dragKalenderCollection"
|
||||
style="border:1px"
|
||||
:style="eventStyle(event.orig)"
|
||||
data-cy="calendar-event"
|
||||
>
|
||||
<button v-if="parked" class="unpark-btn" type="button" @click="unpark">
|
||||
<i class="fa-solid fa-xmark"></i>
|
||||
</button>
|
||||
<div class="title">
|
||||
{{ topicString || event.orig.titel || event.orig.lehrfach }}
|
||||
</div>
|
||||
<div>
|
||||
{{ event.orig.datum }} {{ event.orig.beginn }}–{{ event.orig.ende }}
|
||||
<span v-if="event.ort_kurzbz">· {{ event.orig.ort_kurzbz }}</span>
|
||||
<span class="text-decoration-underline" @click="jumpToKw">KW: {{ kw }}</span> {{ datum }}
|
||||
</div>
|
||||
<div>
|
||||
{{ event.orig.beginn }}–{{ event.orig.ende }}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
};
|
||||
@@ -32,7 +32,8 @@ export default {
|
||||
"prev",
|
||||
"click:mode",
|
||||
"update:date",
|
||||
"update:mode"
|
||||
"update:mode",
|
||||
"update:date-range"
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
@@ -109,6 +110,7 @@ export default {
|
||||
class="btn btn-outline-secondary border-0"
|
||||
@click="$emit('prev')"
|
||||
:disabled="open"
|
||||
v-if="mode !== 'tableList'"
|
||||
>
|
||||
<i class="fa fa-chevron-left"></i>
|
||||
</button>
|
||||
@@ -116,6 +118,7 @@ export default {
|
||||
:mode="mode"
|
||||
:date="date"
|
||||
@update:date="$emit('update:date', $event)"
|
||||
@update:date-range="$emit('update:date-range', $event)"
|
||||
@open="open = true"
|
||||
@closed="open = false"
|
||||
:list-length="modeOptions.length"
|
||||
@@ -124,6 +127,7 @@ export default {
|
||||
class="btn btn-outline-secondary border-0"
|
||||
@click="$emit('next')"
|
||||
:disabled="open"
|
||||
v-if="mode !== 'tableList'"
|
||||
>
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
</button>
|
||||
@@ -131,4 +135,4 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,14 @@ export default {
|
||||
}
|
||||
},
|
||||
emits: [
|
||||
"update:date"
|
||||
"update:date",
|
||||
"update:date-range"
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
rangeEnd: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
convertedDate() {
|
||||
// convert to target TZ then strip TZ Information
|
||||
@@ -34,34 +40,37 @@ export default {
|
||||
},
|
||||
current() {
|
||||
switch (this.mode) {
|
||||
case "month":
|
||||
return {month: this.convertedDate.month-1, year: this.convertedDate.year};
|
||||
case "list":
|
||||
return [this.convertedDate.startOf('day').ts, this.convertedDate.startOf('day').plus({ days: this.listLength }).ts - 1];
|
||||
case "week":
|
||||
case "tableList":
|
||||
return [this.convertedDate.startOf('week', { useLocaleWeeks: true }).ts, this.convertedDate.endOf('week', { useLocaleWeeks: true }).ts];
|
||||
case "day":
|
||||
return this.convertedDate;
|
||||
default:
|
||||
return null;
|
||||
case "month":
|
||||
return {month: this.convertedDate.month-1, year: this.convertedDate.year};
|
||||
case "list":
|
||||
return [this.convertedDate.startOf('day').ts, this.convertedDate.startOf('day').plus({ days: this.listLength }).ts - 1];
|
||||
case "week":
|
||||
return [this.convertedDate.startOf('week', { useLocaleWeeks: true }).ts, this.convertedDate.endOf('week', { useLocaleWeeks: true }).ts];
|
||||
case "tableList":
|
||||
return [this.convertedDate.startOf('day').ts, (this.rangeEnd || this.convertedDate).endOf('day').ts];
|
||||
case "day":
|
||||
return this.convertedDate;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
title() {
|
||||
switch (this.mode) {
|
||||
case "month":
|
||||
return this.date.toLocaleString({ month: 'long', year: 'numeric' });
|
||||
case "week":
|
||||
case "tableList":
|
||||
var year = this.date.localWeekYear;
|
||||
var week = this.date.toFormat('nn');
|
||||
return this.$p.t('calendar/year_kw', { year, week });
|
||||
case "list":
|
||||
return this.date.toLocaleString(luxon.DateTime.DATE_FULL) + '-' + this.date.plus({ days: this.listLength - 1 }).toLocaleString(luxon.DateTime.DATE_FULL);
|
||||
case "day":
|
||||
return this.date.toLocaleString(luxon.DateTime.DATE_FULL);
|
||||
default:
|
||||
return 'View not Supported';
|
||||
case "month":
|
||||
return this.date.toLocaleString({ month: 'long', year: 'numeric' });
|
||||
case "week":
|
||||
var year = this.date.localWeekYear;
|
||||
var week = this.date.toFormat('nn');
|
||||
return this.$p.t('calendar/year_kw', { year, week });
|
||||
case "tableList":
|
||||
const end = this.rangeEnd ? this.rangeEnd.setZone(this.timezone, { keepLocalTime: true }) : this.date;
|
||||
return this.date.toLocaleString(luxon.DateTime.DATE_FULL) + '-' + end.toLocaleString(luxon.DateTime.DATE_FULL);
|
||||
case "list":
|
||||
return this.date.toLocaleString(luxon.DateTime.DATE_FULL) + '-' + this.date.plus({ days: this.listLength - 1 }).toLocaleString(luxon.DateTime.DATE_FULL);
|
||||
case "day":
|
||||
return this.date.toLocaleString(luxon.DateTime.DATE_FULL);
|
||||
default:
|
||||
return 'View not Supported';
|
||||
}
|
||||
},
|
||||
weekStart() {
|
||||
@@ -72,20 +81,28 @@ export default {
|
||||
update(value) {
|
||||
let date;
|
||||
switch (this.mode) {
|
||||
case "month":
|
||||
value.month++;
|
||||
date = luxon.DateTime.fromObject(value).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
|
||||
break;
|
||||
case "list":
|
||||
case "week":
|
||||
case "tableList":
|
||||
date = luxon.DateTime.fromJSDate(value[0]).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
|
||||
break;
|
||||
case "day":
|
||||
date = luxon.DateTime.fromJSDate(value).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
|
||||
break;
|
||||
default:
|
||||
return; // Don't update if the value is invalid!
|
||||
case "month":
|
||||
value.month++;
|
||||
date = luxon.DateTime.fromObject(value).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
|
||||
break;
|
||||
case "list":
|
||||
case "week":
|
||||
date = luxon.DateTime.fromJSDate(value[0]).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
|
||||
break;
|
||||
case "tableList":
|
||||
if (!Array.isArray(value) || !value[0] || !value[1])
|
||||
return;
|
||||
this.rangeEnd = luxon.DateTime.fromJSDate(value[1]);
|
||||
const start = luxon.DateTime.fromJSDate(value[0]).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
|
||||
const end = this.rangeEnd.setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
|
||||
this.$emit('update:date', start);
|
||||
this.$emit('update:date-range', { start, end });
|
||||
return;
|
||||
case "day":
|
||||
date = luxon.DateTime.fromJSDate(value).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
|
||||
break;
|
||||
default:
|
||||
return; // Don't update if the value is invalid!
|
||||
}
|
||||
this.$emit("update:date", date);
|
||||
},
|
||||
@@ -99,8 +116,8 @@ export default {
|
||||
@update:model-value="update"
|
||||
:format="() => title"
|
||||
:month-picker="mode == 'month'"
|
||||
:week-picker="mode == 'week' || mode == 'tableList'"
|
||||
:range="mode == 'list' ? { autoRange: listLength - 1 } : false"
|
||||
:week-picker="mode == 'week'"
|
||||
:range="mode == 'list' ? { autoRange: listLength - 1 } : (mode == 'tableList' ? { partialRange: false } : false)"
|
||||
:text-input="mode == 'day'"
|
||||
:week-start="weekStart"
|
||||
:week-numbers="{ type: weekNumbers }"
|
||||
|
||||
@@ -1,109 +1,57 @@
|
||||
import BaseSlider from '../Base/Slider.js';
|
||||
import TableView from './Table/View.js';
|
||||
|
||||
export default {
|
||||
name: "ModeTable",
|
||||
components: {
|
||||
BaseSlider,
|
||||
TableView
|
||||
},
|
||||
props: {
|
||||
currentDate: {
|
||||
type: luxon.DateTime,
|
||||
required: true
|
||||
},
|
||||
rangeEnd: {
|
||||
type: luxon.DateTime,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
emits: [
|
||||
"update:currentDate",
|
||||
"update:range",
|
||||
"click",
|
||||
"requestModalOpen"
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
focusDate: this.currentDate,
|
||||
rangeOffset: 0
|
||||
focusEnd: this.rangeEnd || this.currentDate
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
range() {
|
||||
let first = this.focusDate.startOf('week', { useLocaleWeeks: true });
|
||||
let last = this.focusDate.endOf('week', { useLocaleWeeks: true });
|
||||
|
||||
if (this.rangeOffset != 0) {
|
||||
if (this.rangeOffset < 0) {
|
||||
first = first.plus({ weeks: this.rangeOffset });
|
||||
} else {
|
||||
last = last.plus({ weeks: this.rangeOffset });
|
||||
}
|
||||
}
|
||||
|
||||
return luxon.Interval.fromDateTimes(first, last);
|
||||
return luxon.Interval.fromDateTimes(this.focusDate.startOf('day'), this.focusEnd.endOf('day'));
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentDate() {
|
||||
if (this.currentDate.locale != this.focusDate.locale) {
|
||||
this.focusDate = this.currentDate;
|
||||
this.$emit('update:range', this.range);
|
||||
} else {
|
||||
this.rangeOffset = this.currentDate.startOf('week', { useLocaleWeeks: true }).diff(this.focusDate.startOf('week', { useLocaleWeeks: true }), 'weeks').weeks;
|
||||
if (this.rangeOffset) {
|
||||
this.$emit('update:range', this.range);
|
||||
this.$refs.slider.slidePages(this.rangeOffset).then(this.updatePage);
|
||||
}
|
||||
}
|
||||
currentDate(newDate) {
|
||||
this.focusDate = newDate;
|
||||
if (!this.rangeEnd)
|
||||
this.focusEnd = newDate;
|
||||
this.$emit('update:range', this.range);
|
||||
},
|
||||
rangeEnd(newEnd) {
|
||||
this.focusEnd = newEnd || this.focusDate;
|
||||
this.$emit('update:range', this.range);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
prevPage() {
|
||||
this.rangeOffset = this.$refs.slider.target - 1;
|
||||
this.$emit('update:range', this.range);
|
||||
this.$refs.slider.prevPage().then(this.updatePage);
|
||||
},
|
||||
nextPage() {
|
||||
this.rangeOffset = this.$refs.slider.target + 1;
|
||||
this.$emit('update:range', this.range);
|
||||
this.$refs.slider.nextPage().then(this.updatePage);
|
||||
},
|
||||
updatePage(weeks) {
|
||||
const newFocusDate = this.focusDate.plus({ weeks });
|
||||
this.focusDate = newFocusDate;
|
||||
this.rangeOffset = 0;
|
||||
this.$emit('update:currentDate', this.focusDate);
|
||||
this.$emit('update:range', this.range);
|
||||
},
|
||||
viewAttrs(weeks) {
|
||||
const day = this.focusDate.plus({ weeks });
|
||||
return { ...this.$attrs, day };
|
||||
},
|
||||
handleClickDefaults(evt) {
|
||||
|
||||
switch (evt.detail.source) {
|
||||
case 'day':
|
||||
// default: Set current-date
|
||||
this.$emit('update:currentDate', evt.detail.value);
|
||||
break;
|
||||
case 'event':
|
||||
// default: Request Modal
|
||||
this.$emit('requestModalOpen', { event: evt.detail.value });
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$emit('update:range', this.range);
|
||||
},
|
||||
template: `
|
||||
<div
|
||||
class="fhc-calendar-mode-week flex-grow-1 position-relative"
|
||||
@cal-click-default.capture="handleClickDefaults"
|
||||
>
|
||||
<base-slider ref="slider" v-slot="slot">
|
||||
<table-view ref="view" v-bind="viewAttrs(slot.offset)">
|
||||
<template v-slot="slot"><slot v-bind="slot" mode="week" /></template>
|
||||
</table-view>
|
||||
</base-slider>
|
||||
<div>
|
||||
<table-view ref="view" v-bind="$attrs" :day="focusDate" :end="focusEnd">
|
||||
<template v-slot="slot"><slot v-bind="slot" mode="week" /></template>
|
||||
</table-view>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
import {CoreFilterCmpt} from "../../../../components/filter/Filter.js";
|
||||
import BsModal from '../../../Bootstrap/Modal.js';
|
||||
import FormInput from "../../../Form/Input.js";
|
||||
import ApiDetails from "../../../../api/lehrveranstaltung/details.js";
|
||||
|
||||
|
||||
export default {
|
||||
name: "TableView",
|
||||
@@ -20,6 +18,10 @@ export default {
|
||||
day: {
|
||||
type: luxon.DateTime,
|
||||
required: true
|
||||
},
|
||||
end: {
|
||||
type: luxon.DateTime,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data()
|
||||
@@ -30,10 +32,13 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
start() {
|
||||
return this.day.startOf('week', { useLocaleWeeks: true });
|
||||
return this.day.startOf('day');
|
||||
},
|
||||
tableEnd() {
|
||||
return this.end.endOf('day');
|
||||
},
|
||||
preparedEvents() {
|
||||
const end = this.start.plus({ days: 7 });
|
||||
const end = this.tableEnd;
|
||||
return this.events
|
||||
.filter(e => e.start < end && e.end > this.start)
|
||||
.sort((a, b) => a.start.ts - b.start.ts)
|
||||
@@ -112,15 +117,6 @@ export default {
|
||||
this.$refs.tableViewTable?.tabulator?.setData(newData);
|
||||
}
|
||||
},
|
||||
/* mounted() {
|
||||
|
||||
this.$api.call(ApiDetails.getRaumtyp())
|
||||
.then(result => {
|
||||
this.raumtyp_array = result.data;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
|
||||
},*/
|
||||
template: /* html */`
|
||||
<div class="fhc-calendar-mode-table-view h-100 overflow-auto">
|
||||
<core-filter-cmpt
|
||||
|
||||
@@ -2,6 +2,8 @@ import CalendarGrid from '../../Base/Grid.js';
|
||||
import LabelDay from '../../Base/Label/Day.js';
|
||||
import LabelDow from '../../Base/Label/Dow.js';
|
||||
import LabelTime from '../../Base/Label/Time.js';
|
||||
import FormInput from "../../../Form/Input.js";
|
||||
|
||||
|
||||
export default {
|
||||
name: "WeekView",
|
||||
@@ -9,7 +11,8 @@ export default {
|
||||
CalendarGrid,
|
||||
LabelDay,
|
||||
LabelDow,
|
||||
LabelTime
|
||||
LabelTime,
|
||||
FormInput
|
||||
},
|
||||
inject: {
|
||||
timeGrid: "timeGrid",
|
||||
@@ -23,6 +26,11 @@ export default {
|
||||
},
|
||||
collapseEmptyDays: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visibleDays: JSON.parse(localStorage.getItem('fhc-calender-visible-days')) ?? [true, true, true, true, true, true, true]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
start() {
|
||||
return this.day.startOf('week', { useLocaleWeeks: true });
|
||||
@@ -44,11 +52,19 @@ export default {
|
||||
const end = this.hoursPlan?.end ?? 23;
|
||||
return Array.from({ length: end - start + 1 }, (e, i) => luxon.Duration.fromObject({ hours: i + start }));
|
||||
}
|
||||
},
|
||||
dayVisibility() {
|
||||
return this.axisMain.map(date => this.visibleDays[date.weekday -1])
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isToday(date) {
|
||||
return date.hasSame(luxon.DateTime.now().setZone(this.timezone), 'day');
|
||||
},
|
||||
toggleDay(day)
|
||||
{
|
||||
this.visibleDays.splice(day, 1, !this.visibleDays[day])
|
||||
localStorage.setItem('fhc-calender-visible-days', JSON.stringify(this.visibleDays))
|
||||
}
|
||||
},
|
||||
template: /* html */`
|
||||
@@ -60,9 +76,10 @@ export default {
|
||||
:axis-main-collapsible="collapseEmptyDays"
|
||||
:snap-to-grid="!!timeGrid"
|
||||
all-day-events
|
||||
:day-visibility="dayVisibility"
|
||||
>
|
||||
<template #main-header="{ date }">
|
||||
<div :class="{ today: isToday(date) }">
|
||||
<template #main-header="{ date, index }">
|
||||
<div :class="{ today: isToday(date) }" class="d-flex flex-column align-items-center">
|
||||
<label-dow
|
||||
v-bind="{ date }"
|
||||
@cal-click="evt => evt.detail.source = 'day'"
|
||||
@@ -70,6 +87,13 @@ export default {
|
||||
<label-day
|
||||
v-bind="{ date }"
|
||||
/>
|
||||
<form-input
|
||||
type="checkbox"
|
||||
:checked="visibleDays[date.weekday - 1]"
|
||||
@change="toggleDay(date.weekday - 1)"
|
||||
@click.stop
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
</template>
|
||||
<template #part-header="{ part }">
|
||||
|
||||
@@ -16,6 +16,10 @@ export default {
|
||||
},
|
||||
inject: {
|
||||
renderers: {from: 'renderers'},
|
||||
canToggleGrid: {
|
||||
from: 'canToggleGrid',
|
||||
default: false
|
||||
},
|
||||
appConfig: {
|
||||
from: 'appConfig',
|
||||
default: {
|
||||
@@ -59,15 +63,21 @@ export default {
|
||||
type: Array,
|
||||
default: () => ['all']
|
||||
},
|
||||
showEvents: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
emits: [
|
||||
"update:date",
|
||||
"update:mode",
|
||||
"update:range",
|
||||
"update:date-range",
|
||||
"drop",
|
||||
"resize",
|
||||
"event-hover",
|
||||
"event-unhover"
|
||||
"event-unhover",
|
||||
"open-reservierung"
|
||||
],
|
||||
|
||||
data() {
|
||||
@@ -146,9 +156,18 @@ export default {
|
||||
return '--event-bg:#' + event.farbe;
|
||||
},
|
||||
updateRange(rangeInterval) {
|
||||
if (this.currentMode === 'tableList')
|
||||
return;
|
||||
|
||||
this.rangeInterval = rangeInterval;
|
||||
this.$emit('update:range', rangeInterval);
|
||||
},
|
||||
handleDateRange({ start, end }) {
|
||||
this.rangeInterval = luxon.Interval.fromDateTimes(start.startOf('day'), end.endOf('day'));
|
||||
this.reset();
|
||||
this.$emit('update:range', this.rangeInterval);
|
||||
this.$emit('update:date-range', { start, end });
|
||||
},
|
||||
ondrop(payload){
|
||||
this.$emit('drop', payload);
|
||||
},
|
||||
@@ -224,10 +243,11 @@ export default {
|
||||
@update:date="(newDate, newMode) => $emit('update:date', newDate, newMode)"
|
||||
@update:mode="(newMode, newDate) => { currentMode = newMode; $emit('update:mode', newMode, newDate) }"
|
||||
@update:range="updateRange"
|
||||
@update:date-range="handleDateRange"
|
||||
>
|
||||
<template v-slot="{ event, mode }">
|
||||
<div
|
||||
:class="['event-type-' + event.type + ' ' + mode + 'PageContainer', { 'event--parked': parkedEvents.has(String(event.kalender_id)) }]"
|
||||
:class="['event-type-' + event.type + ' ' + mode + 'PageContainer', { 'event--parked': parkedEvents.has(String(event.kalender_id)) }, {'event--opacity': !showEvents}]"
|
||||
:type="mode == 'day' ? 'button' : undefined"
|
||||
:style="eventStyle(event)"
|
||||
@mouseenter="$emit('event-hover', event)"
|
||||
@@ -256,6 +276,7 @@ export default {
|
||||
class="d-flex align-items-center gap-2"
|
||||
style="cursor:pointer"
|
||||
@click="showRaster = !showRaster"
|
||||
v-if="canToggleGrid"
|
||||
>
|
||||
<i :class="showRaster ? 'fa-solid fa-toggle-on text-primary' : 'fa-solid fa-toggle-off text-muted'"></i>
|
||||
<span class="form-check-label">Stundenraster</span>
|
||||
@@ -281,4 +302,4 @@ export default {
|
||||
</div>
|
||||
</template>
|
||||
</fhc-calendar>`
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,19 +14,32 @@ export default {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
lecturers: {
|
||||
type: Array,
|
||||
default: [],
|
||||
},
|
||||
studiensemester: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
previewLehreinheitId: {
|
||||
type: [String, Number],
|
||||
default: null
|
||||
},
|
||||
previewLoading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
},
|
||||
emits: ['select-lecturer', 'select-kw'],
|
||||
emits: ['select-lecturer', 'select-kw', 'preview-raumvorschlag'],
|
||||
data() {
|
||||
return {
|
||||
searchparam: '',
|
||||
allCourses: [],
|
||||
sortBy: null,
|
||||
multiWeekIds: new Set(),
|
||||
favorites: new Set()
|
||||
favorites: new Set(),
|
||||
filter: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -86,32 +99,45 @@ export default {
|
||||
studiengaenge: {
|
||||
deep: true,
|
||||
handler(val) {
|
||||
this.searchparam = '';
|
||||
this.loadCoursesByStg(val);
|
||||
this.loadCourses();
|
||||
}
|
||||
},
|
||||
lecturers: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.loadCourses();
|
||||
}
|
||||
},
|
||||
studiensemester() {
|
||||
if (this.studiengaenge)
|
||||
this.loadCoursesByStg(this.studiengaenge);
|
||||
this.loadCourses();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async loadCoursesByStg(stg) {
|
||||
if (stg.length <= 0)
|
||||
{
|
||||
this.allCourses = [];
|
||||
return;
|
||||
async loadCourses()
|
||||
{
|
||||
const hasLektoren = this.lecturers.length > 0;
|
||||
const hasStg = this.studiengaenge.length > 0;
|
||||
|
||||
this.filter = {};
|
||||
if (hasLektoren)
|
||||
this.filter.uid = this.lecturers;
|
||||
|
||||
if (hasStg) {
|
||||
this.filter.stg = this.studiengaenge.map(
|
||||
({ stg_kz, semester, orgform_kurzbz }) => ({
|
||||
stg_kz,
|
||||
semester,
|
||||
orgform_kurzbz,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
let payload = stg.map(({ stg_kz, semester, orgform_kurzbz }) => ({
|
||||
stg_kz,
|
||||
semester,
|
||||
orgform_kurzbz
|
||||
}));
|
||||
|
||||
this.$api.call(ApiCoursePicker.getByStg(payload, this.studiensemester))
|
||||
if (Object.keys(this.filter).length === 0)
|
||||
return this.allCourses = [];
|
||||
this.$api.call(ApiCoursePicker.getCourses(this.filter, this.studiensemester))
|
||||
.then(result => {
|
||||
this.allCourses = result.data.map(e => ({
|
||||
this.allCourses = result?.data?.map(e => ({
|
||||
lehreinheit_id: e.lehreinheit_id,
|
||||
lektoren: e.lektoren,
|
||||
raumtyp: e.raumtyp,
|
||||
@@ -177,7 +203,7 @@ export default {
|
||||
},
|
||||
reload()
|
||||
{
|
||||
this.loadCoursesByStg(this.studiengaenge);
|
||||
this.loadCourses();
|
||||
},
|
||||
toggleMultiWeek(course)
|
||||
{
|
||||
@@ -210,6 +236,17 @@ export default {
|
||||
{
|
||||
return this.favorites.has(course.lehreinheit_id);
|
||||
},
|
||||
selectRaumvorschlag(course)
|
||||
{
|
||||
if (this.isRaumvorschlagActive(course))
|
||||
this.$emit('preview-raumvorschlag', null);
|
||||
else
|
||||
this.$emit('preview-raumvorschlag', course.orig);
|
||||
},
|
||||
isRaumvorschlagActive(course)
|
||||
{
|
||||
return this.previewLehreinheitId != null && this.previewLehreinheitId === course.lehreinheit_id;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.favorites = new Set(JSON.parse(localStorage.getItem('tempus_coursepicker_favs') || '[]'));
|
||||
@@ -253,7 +290,7 @@ export default {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="studiengaenge.length <= 0" class="d-flex flex-column align-items-center justify-content-center text-center text-muted py-5 px-3 h-100">
|
||||
<div v-if="Object.keys(filter).length <= 0" class="d-flex flex-column align-items-center justify-content-center text-center text-muted py-5 px-3 h-100">
|
||||
<span class="small fw-semibold mb-1">{{$p.t('lehre', 'cptitleempty')}}</span>
|
||||
<span class="small">{{$p.t('lehre', 'cpempty')}}</span>
|
||||
</div>
|
||||
@@ -264,7 +301,7 @@ export default {
|
||||
style="cursor:grab"
|
||||
:style="courseStyle(course)"
|
||||
class="course-picker-row rounded-3 mb-2 p-2"
|
||||
:class="{ 'course-picker-row-pinned': isPinned(course) }"
|
||||
:class="{ 'course-picker-row-pinned': isPinned(course), 'course-picker-row-preview': isRaumvorschlagActive(course) }"
|
||||
v-draggable:move.noimage="dragLehreinheitCollection(course)"
|
||||
tabindex="0"
|
||||
>
|
||||
@@ -284,6 +321,19 @@ export default {
|
||||
v-tooltip="isMultiWeek(course) ? 'MultiWeek aktiv' : 'MultiWeek Verplanung aktivieren'"
|
||||
@click.stop="toggleMultiWeek(course)"
|
||||
></i>
|
||||
<i
|
||||
v-if="!(previewLoading && isRaumvorschlagActive(course))"
|
||||
class="fa fa-door-open"
|
||||
:class="isRaumvorschlagActive(course) ? 'text-primary' : 'text-muted'"
|
||||
style="cursor:pointer"
|
||||
v-tooltip="isRaumvorschlagActive(course) ? 'Raumvorschlag ausblenden' : 'Raumvorschlag einblenden'"
|
||||
@click.stop="selectRaumvorschlag(course)"
|
||||
></i>
|
||||
<i
|
||||
v-else
|
||||
class="fa fa-spinner fa-spin text-primary"
|
||||
v-tooltip="'Räume werden geprüft...'"
|
||||
></i>
|
||||
</div>
|
||||
|
||||
<!--TODO(david) entfernen, dient nur für das mappen mit der lvverwaltung-->
|
||||
|
||||
@@ -47,6 +47,10 @@ export default {
|
||||
<i :class="l.overlays.wishes ? 'fa-solid fa-toggle-on text-primary' : 'fa-solid fa-toggle-off text-muted'"></i>
|
||||
<span class="form-check-label">Zeitwünsche</span>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-2" @click="l.showCoursePicker = !l.showCoursePicker" style="cursor:pointer">
|
||||
<i :class="l.showCoursePicker ? 'fa-solid fa-toggle-on text-primary' : 'fa-solid fa-toggle-off text-muted'"></i>
|
||||
<span class="form-check-label">Course Picker</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -43,6 +43,25 @@ export function getTempusSearchbarOptions(self)
|
||||
self.addToFilter(data, 'mitarbeiter');
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "zum Course Picker hinzufügen",
|
||||
icon: "fas fa-plus",
|
||||
type: "function",
|
||||
action: (data) => {
|
||||
self.addToCoursePicker(data);
|
||||
}
|
||||
},
|
||||
{
|
||||
label: "LVVerwaltung",
|
||||
icon: "fas fa-up-right-from-square",
|
||||
type: "function",
|
||||
action: (data) => {
|
||||
const link = FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router +
|
||||
"/LVVerwaltung/stdsem/" + self.selectedStudiensemester + "/emp/" + data.uid;
|
||||
window.open(link, "_blank");
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
@@ -20,11 +20,10 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ["focus-searchbar", "language-changed"],
|
||||
emits: ["language-changed"],
|
||||
methods: {
|
||||
focusSearchbar() {
|
||||
this.$refs.searchbar?.$refs?.input?.focus();
|
||||
this.$emit("focus-searchbar");
|
||||
},
|
||||
},
|
||||
template: /* html */ `
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
import BsModal from '../Bootstrap/Modal.js';
|
||||
import CoreForm from '../Form/Form.js';
|
||||
import FormValidation from '../Form/Validation.js';
|
||||
import FormInput from '../Form/Input.js';
|
||||
|
||||
import ApiTempusSync from '../../api/factory/tempus/sync.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
BsModal,
|
||||
CoreForm,
|
||||
FormValidation,
|
||||
FormInput
|
||||
},
|
||||
props: {
|
||||
config: Object,
|
||||
stsem_kurzbz: String
|
||||
},
|
||||
emits: [
|
||||
'saved'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
mode: 'new',
|
||||
formData: {},
|
||||
studienplaene: [],
|
||||
max_semester: null,
|
||||
syncStati: [],
|
||||
loading: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
semester() {
|
||||
if (!this.max_semester)
|
||||
return [];
|
||||
|
||||
return Array.from({length: this.max_semester}, (_, index) => index);
|
||||
},
|
||||
studienplanTrigger() {
|
||||
return [
|
||||
this.formData.oe_kurzbz,
|
||||
this.formData.studiensemester_kurzbz,
|
||||
this.formData.ausbildungssemester
|
||||
].join('|');
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'formData.oe_kurzbz'(newOrganisation)
|
||||
{
|
||||
if (!newOrganisation) {
|
||||
this.max_semester = null;
|
||||
this.studienplaene = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let filtered_org = (this.config.organisationen ?? []).filter(org => org.oe_kurzbz === newOrganisation)[0];
|
||||
|
||||
if (filtered_org && filtered_org.studiengang_kz)
|
||||
this.getSemester(filtered_org.studiengang_kz);
|
||||
else
|
||||
this.max_semester = null;
|
||||
},
|
||||
studienplanTrigger() {
|
||||
this.getStudienplan();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
openNew() {
|
||||
this.$refs.modal.hide();
|
||||
|
||||
this.mode = 'new';
|
||||
this.max_semester = null;
|
||||
this.studienplaene = [];
|
||||
this.formData = {
|
||||
oe_kurzbz: null,
|
||||
studiensemester_kurzbz: this.stsem_kurzbz ?? null,
|
||||
datum_bis: null,
|
||||
studienplan_id: null,
|
||||
ausbildungssemester: null,
|
||||
sync_status_kurzbz: null,
|
||||
mail: false
|
||||
};
|
||||
|
||||
this.$refs.form.clearValidation()
|
||||
this.$refs.modal.show()
|
||||
},
|
||||
openEdit(entry) {
|
||||
if (!entry || entry.kalender_syncstatus_id === undefined || entry.kalender_syncstatus_id === null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.$refs.modal.hide();
|
||||
this.mode = 'edit';
|
||||
|
||||
this.$api
|
||||
.call(ApiTempusSync.loadSync(entry.kalender_syncstatus_id))
|
||||
.then(result => {
|
||||
this.formData = result.data;
|
||||
return this.$refs.form.clearValidation();
|
||||
})
|
||||
.then(() => this.$refs.modal.show())
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
|
||||
openStart() {
|
||||
this.$refs.modal.hide();
|
||||
|
||||
this.mode = 'start';
|
||||
this.max_semester = null;
|
||||
this.studienplaene = [];
|
||||
this.formData = {
|
||||
oe_kurzbz: null,
|
||||
studiensemester_kurzbz: this.stsem_kurzbz ?? null,
|
||||
datum_bis: null,
|
||||
sync_status_kurzbz: null,
|
||||
studienplan_id: null,
|
||||
ausbildungssemester: null,
|
||||
mail: false
|
||||
};
|
||||
|
||||
this.$refs.form.clearValidation()
|
||||
this.$refs.modal.show()
|
||||
},
|
||||
getSemester(stg_kz) {
|
||||
this.$api.call(ApiTempusSync.getMaxSemester([stg_kz]))
|
||||
.then(response => response.data)
|
||||
.then(response => {
|
||||
this.max_semester = response ?? null;
|
||||
|
||||
let found = this.semester.filter(semester => semester === this.formData.ausbildungssemester);
|
||||
if (found.length === 0)
|
||||
this.formData.ausbildungssemester = null;
|
||||
})
|
||||
.catch(error => {
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
});
|
||||
},
|
||||
getStudienplan() {
|
||||
if (!this.formData.oe_kurzbz || !this.formData.studiensemester_kurzbz) {
|
||||
this.studienplaene = [];
|
||||
return;
|
||||
}
|
||||
|
||||
this.$api.call(ApiTempusSync.getStudienplan(
|
||||
this.formData.oe_kurzbz,
|
||||
this.formData.studiensemester_kurzbz,
|
||||
this.formData.ausbildungssemester ?? null
|
||||
))
|
||||
.then(response => response.data)
|
||||
.then(response => {
|
||||
this.studienplaene = response ?? [];
|
||||
let found = this.studienplaene.filter(plan => plan.studienplan_id === this.formData.studienplan_id);
|
||||
if (found.length === 0)
|
||||
this.formData.studienplan_id = null;
|
||||
})
|
||||
.catch(error => {
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
});
|
||||
},
|
||||
save() {
|
||||
if (this.mode === 'start')
|
||||
this.start();
|
||||
else if (this.mode === 'new')
|
||||
this.insert();
|
||||
else
|
||||
this.update();
|
||||
},
|
||||
insert() {
|
||||
this.$refs.form
|
||||
.call(ApiTempusSync.add(this.formData))
|
||||
.then(() => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
|
||||
this.$emit('saved', this.formData.studiensemester_kurzbz);
|
||||
this.$refs.modal.hide();
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
update() {
|
||||
this.$refs.form
|
||||
.call(ApiTempusSync.updateSync(this.formData))
|
||||
.then(() => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
|
||||
this.$emit('saved', this.formData.studiensemester_kurzbz);
|
||||
this.$refs.modal.hide();
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
},
|
||||
start(data) {
|
||||
this.loading = true;
|
||||
return this.$refs.form
|
||||
.call(ApiTempusSync.start(data ?? this.formData))
|
||||
.then(() => {
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successStart'));
|
||||
this.$refs.modal.hide();
|
||||
this.loading = false;
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError)
|
||||
.finally(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
hideModal()
|
||||
{
|
||||
this.formData = {}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
this.$api
|
||||
.call(ApiTempusSync.getSyncStatus())
|
||||
.then(result => this.syncStati = result.data ?? [])
|
||||
.catch(error => this.$fhcAlert.handleSystemError(error));
|
||||
},
|
||||
template: `
|
||||
<bs-modal ref="modal" @hideBsModal="hideModal">
|
||||
<template #title>
|
||||
<template v-if="mode === 'new'">{{ $p.t('lehre', 'tempus_sync_new') }}</template>
|
||||
<template v-else-if="mode === 'edit'">{{ $p.t('lehre', 'tempus_sync_edit') }}</template>
|
||||
<template v-else>{{ $p.t('lehre', 'tempus_sync_start') }}</template>
|
||||
</template>
|
||||
|
||||
<core-form ref="form">
|
||||
<form-validation></form-validation>
|
||||
|
||||
<form-input
|
||||
container-class="mb-3"
|
||||
type="select"
|
||||
v-model="formData.oe_kurzbz"
|
||||
name="oe_kurzbz"
|
||||
:label="$p.t('lehre/organisationseinheit')"
|
||||
required
|
||||
>
|
||||
<option
|
||||
v-for="organisation in config.organisationen"
|
||||
:key="organisation.oe_kurzbz"
|
||||
:value="organisation.oe_kurzbz"
|
||||
>
|
||||
[{{ organisation.organisationseinheittyp_kurzbz }}] {{ organisation.bezeichnung }} {{ ['b', 'm'].includes(organisation.typ) ? organisation.stgbezeichnung : '' }}
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
container-class="mb-3"
|
||||
type="select"
|
||||
v-model="formData.studiensemester_kurzbz"
|
||||
name="studiensemester_kurzbz"
|
||||
:label="$p.t('lehre/studiensemester')"
|
||||
required
|
||||
>
|
||||
<option
|
||||
v-for="studiensemester in config.studiensemestern"
|
||||
:key="studiensemester.studiensemester_kurzbz"
|
||||
:value="studiensemester.studiensemester_kurzbz"
|
||||
>
|
||||
{{ studiensemester.studiensemester_kurzbz }}
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
container-class="mb-3"
|
||||
type="select"
|
||||
v-model="formData.ausbildungssemester"
|
||||
name="ausbildungssemester"
|
||||
:label="$p.t('lehre/ausbildungssemester')"
|
||||
:disabled="!max_semester"
|
||||
>
|
||||
<option :value="null">-- {{ $p.t('fehlermonitoring', 'keineAuswahl') }} --</option>
|
||||
<option
|
||||
v-for="number in semester"
|
||||
:key="number"
|
||||
:value="number"
|
||||
>
|
||||
{{ number }}
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
container-class="mb-3"
|
||||
type="select"
|
||||
v-model="formData.studienplan_id"
|
||||
name="studienplan_id"
|
||||
:label="$p.t('lehre/studienplan')"
|
||||
:disabled="!studienplaene.length"
|
||||
>
|
||||
<option :value="null">-- {{ $p.t('fehlermonitoring', 'keineAuswahl') }} --</option>
|
||||
<option
|
||||
v-for="plan in studienplaene"
|
||||
:key="plan.studienplan_id"
|
||||
:value="plan.studienplan_id"
|
||||
>
|
||||
{{ plan.bezeichnung }}-{{plan.orgform_kurzbz}}
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
container-class="mb-3"
|
||||
type="DatePicker"
|
||||
v-model="formData.datum_bis"
|
||||
name="datum_bis"
|
||||
:label="$p.t('ui/dateTo')"
|
||||
auto-apply
|
||||
:enable-time-picker="false"
|
||||
text-input
|
||||
format="dd.MM.yyyy"
|
||||
preview-format="dd.MM.yyyy"
|
||||
:teleport="true"
|
||||
>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
|
||||
container-class="mb-3"
|
||||
type="select"
|
||||
v-model="formData.sync_status_kurzbz"
|
||||
name="sync_status_kurzbz"
|
||||
:label="$p.t('global/status')"
|
||||
>
|
||||
<option :value="null">-- {{ $p.t('fehlermonitoring', 'keineAuswahl') }} --</option>
|
||||
<option
|
||||
v-for="status in syncStati"
|
||||
:key="status.status_kurzbz"
|
||||
:value="status.status_kurzbz"
|
||||
>
|
||||
{{ status.bezeichnung }}
|
||||
</option>
|
||||
</form-input>
|
||||
|
||||
<form-input
|
||||
container-class="mb-3"
|
||||
type="checkbox"
|
||||
v-model="formData.mail"
|
||||
name="mail"
|
||||
:label="$p.t('lehre/mail_benachrichtigung')"
|
||||
>
|
||||
</form-input>
|
||||
|
||||
</core-form>
|
||||
|
||||
<template #footer>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-primary"
|
||||
@click="save"
|
||||
:disabled="loading"
|
||||
>
|
||||
<template v-if="mode === 'start'">{{ $p.t('global', 'jetztStarten') }}</template>
|
||||
<template v-else>{{ $p.t('ui', 'ok') }}</template>
|
||||
</button>
|
||||
</template>
|
||||
</bs-modal>`
|
||||
};
|
||||
@@ -9,7 +9,7 @@ export default {
|
||||
directives: {
|
||||
drop
|
||||
},
|
||||
emits: ['update:parkedKeys'],
|
||||
emits: ['update:parkedKeys', 'select-kw'],
|
||||
data() {
|
||||
return {
|
||||
parked: [],
|
||||
@@ -66,11 +66,12 @@ export default {
|
||||
>
|
||||
<i v-if="!parked.length" class="fa-solid fa-square-parking"></i>
|
||||
<event-card
|
||||
class="parkingevent"
|
||||
v-for="parkedEvent in parked"
|
||||
:key="parkedEvent.id"
|
||||
:event="parkedEvent"
|
||||
parked
|
||||
@select-kw="$emit('select-kw', $event)"
|
||||
@unpark="unpark"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import BsModal from "../Bootstrap/Modal.js";
|
||||
import ApiKalender from "../../api/factory/tempus/kalender.js";
|
||||
import FormInput from "../../../js/components/Form/Input.js";
|
||||
|
||||
|
||||
export default {
|
||||
name: "RaumauswahlModal",
|
||||
components: {
|
||||
BsModal,
|
||||
Listbox: primevue.listbox,
|
||||
FormInput
|
||||
},
|
||||
emits: ["saved"],
|
||||
data() {
|
||||
@@ -14,6 +17,9 @@ export default {
|
||||
selectedRooms: [],
|
||||
event: null,
|
||||
loading: false,
|
||||
mode: 'edit',
|
||||
pendingEvent: null,
|
||||
location: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
@@ -22,10 +28,12 @@ export default {
|
||||
if (!orig?.kalender_id)
|
||||
return;
|
||||
|
||||
this.mode = 'edit';
|
||||
this.event = orig;
|
||||
this.loading = true;
|
||||
this.entries = [];
|
||||
this.selectedRooms = [];
|
||||
this.location = this.event.location
|
||||
|
||||
this.$refs.modal.show();
|
||||
|
||||
@@ -53,13 +61,51 @@ export default {
|
||||
},
|
||||
hide() {
|
||||
this.selectedRooms = [];
|
||||
this.pendingEvent = null;
|
||||
|
||||
this.$refs.modal.hide();
|
||||
},
|
||||
async confirm() {
|
||||
let ort_kurzbz = this.selectedRooms.map((room) => room.ort_kurzbz);
|
||||
showForNew(lehreinheit_id, start_time, end_time, vorschlaege)
|
||||
{
|
||||
this.mode = 'new'
|
||||
this.pendingEvent = {lehreinheit_id, start_time, end_time}
|
||||
this.event = null;
|
||||
this.loading = false;
|
||||
this.entries = vorschlaege ?? [];
|
||||
this.selectedRooms = [];
|
||||
|
||||
if (ort_kurzbz.length < 1)
|
||||
this.$refs.modal.show();
|
||||
},
|
||||
|
||||
async confirm() {
|
||||
|
||||
if (this.mode === 'new')
|
||||
{
|
||||
const result = await this.$api.call(
|
||||
ApiKalender.addKalenderEvent(
|
||||
this.pendingEvent.lehreinheit_id,
|
||||
this.selectedRooms.map((room) => room.ort_kurzbz),
|
||||
this.pendingEvent.start_time,
|
||||
this.pendingEvent.end_time
|
||||
)
|
||||
).then((result) => result.data)
|
||||
|
||||
if (result.needs_room_selection)
|
||||
{
|
||||
this.showForNew(this.pendingEvent.lehreinheit_id, this.pendingEvent.start_time, this.pendingEvent.end_time, result.raum_vorschlaege);
|
||||
return;
|
||||
}
|
||||
|
||||
this.hide();
|
||||
this.$emit('saved');
|
||||
return;
|
||||
}
|
||||
let orte = {};
|
||||
|
||||
orte.ort_kurzbz = this.selectedRooms.map((room) => room.ort_kurzbz);
|
||||
orte.location = this.location;
|
||||
|
||||
if (orte.ort_kurzbz.length < 1 && orte.location?.trim().length < 1)
|
||||
{
|
||||
await this.$api.call(
|
||||
ApiKalender.deleteOrtEntry(this.event.kalender_id),
|
||||
@@ -68,7 +114,7 @@ export default {
|
||||
else
|
||||
{
|
||||
await this.$api.call(
|
||||
ApiKalender.updateKalenderEvent(this.event.kalender_id, {ort_kurzbz}),
|
||||
ApiKalender.updateKalenderEvent(this.event.kalender_id, {orte}),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -119,16 +165,38 @@ export default {
|
||||
listStyle="max-height: 300px"
|
||||
:emptyMessage="$p.t('ui', 'keineEintraegeGefunden')"
|
||||
>
|
||||
<template #option="{ option }">
|
||||
<div class="d-flex justify-content-between w-100">
|
||||
<span><i class="fa-solid fa-door-open me-2"></i>{{ option.ort_kurzbz }}</span>
|
||||
<span
|
||||
class="text-muted"
|
||||
v-tooltip="{ value: (option.details || []).join('\\n'), class: 'custom-tooltip' }"
|
||||
>{{ option.score }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #option="{ option }">
|
||||
<div class="room-option">
|
||||
<i class="fa-solid fa-door-open text-muted"></i>
|
||||
<span v-if="option.raumtyp_kurzbz">
|
||||
[{{ option.raumtyp_kurzbz }}]
|
||||
</span>
|
||||
<span v-else></span>
|
||||
<span class="fw-semibold">
|
||||
{{ option.ort_kurzbz }}
|
||||
</span>
|
||||
<span class="text-muted small text-nowrap">
|
||||
{{ option.max_person }} Pers.
|
||||
</span>
|
||||
<span
|
||||
class="text-muted text-end"
|
||||
v-tooltip="{ value: (option.details || []).join('\\n'), class: 'custom-tooltip' }"
|
||||
>
|
||||
{{ option.score }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</Listbox>
|
||||
<form-input
|
||||
v-if="mode === 'edit'"
|
||||
label="Location"
|
||||
type="textarea"
|
||||
container-class="col-12"
|
||||
name="location"
|
||||
v-model="location"
|
||||
></form-input>
|
||||
|
||||
<div class="d-flex justify-content-end gap-2 mt-3">
|
||||
<button type="button" class="btn btn-secondary" @click="hide">
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
export default {
|
||||
props:{
|
||||
props: {
|
||||
event: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed:{
|
||||
computed: {
|
||||
classes() {
|
||||
const classes = ['cis-renderer-lehreinheit-calendar-event', 'calendar-event-default', 'h-100', 'w-100', 'p-1'];
|
||||
const classes = [
|
||||
'cis-renderer-lehreinheit-calendar-event',
|
||||
'calendar-event-default',
|
||||
'h-100',
|
||||
'w-100',
|
||||
'p-1',
|
||||
];
|
||||
|
||||
if (this.event.collisions) {
|
||||
classes.push('calendar-event-collisions');
|
||||
@@ -16,67 +22,79 @@ export default {
|
||||
return classes;
|
||||
},
|
||||
topicString() {
|
||||
return Array.isArray(this.event.topic) ? this.event.topic.join(', ') : this.event.topic;
|
||||
return Array.isArray(this.event.topic)
|
||||
? this.event.topic.join(', ')
|
||||
: this.event.topic;
|
||||
},
|
||||
ortString() {
|
||||
return Array.isArray(this.event.ort_kurzbz) ? this.event.ort_kurzbz.join(', ') : this.event.ort_kurzbz;
|
||||
let orte = [
|
||||
...(this.event.ort_kurzbz || []),
|
||||
this.event.location?.trim(),
|
||||
].filter(Boolean);
|
||||
return orte.join(', ');
|
||||
},
|
||||
gruppeString() {
|
||||
return Array.isArray(this.event.gruppe)
|
||||
? this.event.gruppe.map(gruppe => gruppe.bezeichnung).join(', ')
|
||||
? this.event.gruppe.map((gruppe) => gruppe.bezeichnung).join(', ')
|
||||
: this.event.gruppe;
|
||||
},
|
||||
tooltipString() {
|
||||
const tooltipArray = [];
|
||||
|
||||
tooltipArray.push([
|
||||
this.$p.t('global/uhrzeit'),
|
||||
[this.start, this.end].join(' - ')
|
||||
].join(": "));
|
||||
tooltipArray.push(
|
||||
[this.$p.t('global/uhrzeit'), [this.start, this.end].join(' - ')].join(
|
||||
': ',
|
||||
),
|
||||
);
|
||||
|
||||
tooltipArray.push([
|
||||
this.$p.t('profilUpdate/topic'),
|
||||
this.topicString
|
||||
].join(": "));
|
||||
tooltipArray.push(
|
||||
[this.$p.t('profilUpdate/topic'), this.topicString].join(': '),
|
||||
);
|
||||
|
||||
tooltipArray.push([
|
||||
this.$p.t('person/ort'),
|
||||
this.ortString
|
||||
].join(": "));
|
||||
tooltipArray.push([this.$p.t('person/ort'), this.ortString].join(': '));
|
||||
|
||||
if (this.gruppeString) {
|
||||
tooltipArray.push([
|
||||
this.$p.t('lehre/gruppe'),
|
||||
this.gruppeString
|
||||
].join(": "));
|
||||
tooltipArray.push(
|
||||
[this.$p.t('lehre/gruppe'), this.gruppeString].join(': '),
|
||||
);
|
||||
}
|
||||
|
||||
if (Array.isArray(this.event.lektor) && this.event.lektor.length > 0) {
|
||||
if (this.event.lektor.length > 3) {
|
||||
tooltipArray.push([
|
||||
this.$p.t('lehre/lektor'),
|
||||
this.event.lektor.slice(0, 3).map(lektor => lektor.kurzbz).join("\n")
|
||||
+ "\n" + this.$p.t('lehre/weitereLektoren', [this.event.lektor.length - 3])
|
||||
].join(": "));
|
||||
tooltipArray.push(
|
||||
[
|
||||
this.$p.t('lehre/lektor'),
|
||||
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 {
|
||||
tooltipArray.push([
|
||||
this.$p.t('lehre/lektor'),
|
||||
this.event.lektor.map(lektor => lektor.kurzbz).join("\n")
|
||||
].join(": "));
|
||||
tooltipArray.push(
|
||||
[
|
||||
this.$p.t('lehre/lektor'),
|
||||
this.event.lektor.map((lektor) => lektor.kurzbz).join('\n'),
|
||||
].join(': '),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return tooltipArray.join("\n");
|
||||
return tooltipArray.join('\n');
|
||||
},
|
||||
start() {
|
||||
return luxon.Duration
|
||||
.fromISOTime(this.event.beginn)
|
||||
.toISOTime({ suppressSeconds: true });
|
||||
return luxon.Duration.fromISOTime(this.event.beginn).toISOTime({
|
||||
suppressSeconds: true,
|
||||
});
|
||||
},
|
||||
end() {
|
||||
return luxon.Duration
|
||||
.fromISOTime(this.event.ende)
|
||||
.toISOTime({ suppressSeconds: true });
|
||||
return luxon.Duration.fromISOTime(this.event.ende).toISOTime({
|
||||
suppressSeconds: true,
|
||||
});
|
||||
},
|
||||
tags() {
|
||||
if (typeof this.event.tags === 'string') {
|
||||
@@ -87,7 +105,7 @@ export default {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return this.event.tags || [];
|
||||
},
|
||||
tagsTooltip() {
|
||||
@@ -95,7 +113,7 @@ export default {
|
||||
return '';
|
||||
}
|
||||
|
||||
return this.tags.map(tag => tag.beschreibung).join("\n");
|
||||
return this.tags.map((tag) => tag.beschreibung).join('\n');
|
||||
},
|
||||
resourcesTooltip() {
|
||||
if (!this.event.resources || this.event.resources.length === 0) {
|
||||
@@ -112,10 +130,10 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
return resources.map(resource => resource.beschreibung).join("\n");
|
||||
return resources.map((resource) => resource.beschreibung).join('\n');
|
||||
},
|
||||
},
|
||||
template: /*html*/`
|
||||
template: /*html*/ `
|
||||
<div
|
||||
:class="classes"
|
||||
class="position-relative"
|
||||
@@ -133,6 +151,9 @@ export default {
|
||||
class="fa-solid fa-tags"
|
||||
></i>
|
||||
</div>
|
||||
<div class="position-absolute bottom-0 start-0 m-1">
|
||||
{{event.verplante_stunden}}
|
||||
</div>
|
||||
<div
|
||||
v-if="!event.allDayEvent && event?.beginn && event?.ende"
|
||||
class="event-time d-none d-xl-grid h-100"
|
||||
@@ -162,4 +183,4 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -80,9 +80,6 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
mehtodNumberPadding: function (number) {
|
||||
return numberPadding(number);
|
||||
},
|
||||
methodFormatDate: function (d) {
|
||||
return formatDate(d);
|
||||
},
|
||||
@@ -200,4 +197,4 @@ export default {
|
||||
|
||||
<lv-menu :containerStyles="['p-0']" :rowStyles="['m-0']" v-if="lvMenu.length" :menu="lvMenu" />
|
||||
</div>`,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,8 @@ export default {
|
||||
.toISOTime({ suppressSeconds: true });
|
||||
},
|
||||
ortString() {
|
||||
return Array.isArray(this.event.ort_kurzbz) ? this.event.ort_kurzbz.join(', ') : this.event.ort_kurzbz;
|
||||
let orte = [...(this.event.ort_kurzbz || []), this.event.location?.trim()].filter(Boolean)
|
||||
return orte.join(', ')
|
||||
},
|
||||
topicString() {
|
||||
return Array.isArray(this.event.titel) ? this.event.titel.join(', ') : this.event.titel;
|
||||
|
||||
@@ -52,9 +52,6 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
mehtodNumberPadding: function (number) {
|
||||
return numberPadding(number);
|
||||
},
|
||||
methodFormatDate: function (d) {
|
||||
return formatDate(d);
|
||||
},
|
||||
@@ -133,4 +130,4 @@ export default {
|
||||
</table>
|
||||
|
||||
</div>`,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,8 @@ export default {
|
||||
show_all_fields: false,
|
||||
filteredUsers: [],
|
||||
filteredGroups: [],
|
||||
abortController: null
|
||||
abortController: null,
|
||||
location: null
|
||||
};
|
||||
},
|
||||
created()
|
||||
@@ -141,11 +142,16 @@ export default {
|
||||
},
|
||||
save()
|
||||
{
|
||||
|
||||
let orte = {
|
||||
ort_kurzbz: this.selected_rooms.map(r => r.ort_kurzbz),
|
||||
location: this.location
|
||||
}
|
||||
this.$api.call(
|
||||
ApiReservierung.addReservierung(
|
||||
this.titel,
|
||||
this.beschreibung,
|
||||
this.selected_rooms.map(r => r.ort_kurzbz),
|
||||
orte,
|
||||
luxon.DateTime.fromFormat(this.start, 'yyyy-MM-dd HH:mm').toISO(),
|
||||
luxon.DateTime.fromFormat(this.end, 'yyyy-MM-dd HH:mm').toISO(),
|
||||
this.teilnehmer.filter(t => t.uid && t.rolle).map(nehmer => ({ uid: nehmer.uid, rolle: nehmer.rolle })),
|
||||
@@ -220,6 +226,14 @@ export default {
|
||||
</template>
|
||||
</Multiselect>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<form-input
|
||||
:label="$p.t('global', 'raum')"
|
||||
type="textarea"
|
||||
name="location"
|
||||
v-model="location"
|
||||
></form-input>
|
||||
</div>
|
||||
<div class="col-12" v-if="show_all_fields">
|
||||
<div v-for="(nehmer, i) in teilnehmer" :key="i" class="d-flex gap-2 mb-2 align-items-end">
|
||||
<form-input
|
||||
|
||||
@@ -1,75 +1,92 @@
|
||||
import FhcCoursepicker from "./Coursepicker.js";
|
||||
import LectureSelection from "./Filters/LectureSelection.js";
|
||||
import VerbandSelection from "./Filters/VerbandSelection.js";
|
||||
import RoomSelection from "./Filters/RoomSelection.js";
|
||||
import ParkingSlot from "./ParkingSlot.js";
|
||||
import StvStudiensemester from "../Stv/Studentenverwaltung/Studiensemester.js";
|
||||
import FhcCoursepicker from './Coursepicker.js';
|
||||
import LectureSelection from './Filters/LectureSelection.js';
|
||||
import VerbandSelection from './Filters/VerbandSelection.js';
|
||||
import RoomSelection from './Filters/RoomSelection.js';
|
||||
import ParkingSlot from './ParkingSlot.js';
|
||||
import StvStudiensemester from '../Stv/Studentenverwaltung/Studiensemester.js';
|
||||
|
||||
export default {
|
||||
name: "TempusSidebarMenu",
|
||||
components: {
|
||||
FhcCoursepicker,
|
||||
LectureSelection,
|
||||
VerbandSelection,
|
||||
RoomSelection,
|
||||
ParkingSlot,
|
||||
StvStudiensemester,
|
||||
},
|
||||
props: {
|
||||
previewRole: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
rooms: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
studiengaenge: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
studiengaengeAll: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
lecturers: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
selectedStudiensemester: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
"update:previewRole",
|
||||
"update:rooms",
|
||||
"update:studiengaenge",
|
||||
"update:parkedKeys",
|
||||
"update:selectedStudiensemester",
|
||||
"remove-lecturer",
|
||||
"select-lecturer",
|
||||
"select-kw",
|
||||
"sync",
|
||||
],
|
||||
methods: {
|
||||
reloadCoursepicker() {
|
||||
return this.$refs.coursepicker?.reload();
|
||||
},
|
||||
isParked(id) {
|
||||
return this.$refs.parking?.isParked(id) ?? false;
|
||||
},
|
||||
park(items) {
|
||||
return this.$refs.parking?.park(null, items);
|
||||
},
|
||||
unpark(item) {
|
||||
return this.$refs.parking?.unpark(item);
|
||||
},
|
||||
},
|
||||
template: /* html */ `
|
||||
name: 'TempusSidebarMenu',
|
||||
components: {
|
||||
FhcCoursepicker,
|
||||
LectureSelection,
|
||||
VerbandSelection,
|
||||
RoomSelection,
|
||||
ParkingSlot,
|
||||
StvStudiensemester,
|
||||
},
|
||||
props: {
|
||||
previewRole: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
rooms: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
studiengaenge: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
studiengaengeAll: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
lecturers: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
selectedStudiensemester: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
raumvorschlagPreview: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
raumvorschlagLoading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: [
|
||||
'update:previewRole',
|
||||
'update:rooms',
|
||||
'update:studiengaenge',
|
||||
'update:parkedKeys',
|
||||
'update:selectedStudiensemester',
|
||||
'remove-lecturer',
|
||||
'select-lecturer',
|
||||
'select-kw',
|
||||
'sync',
|
||||
'preview-raumvorschlag',
|
||||
],
|
||||
methods: {
|
||||
reloadCoursepicker() {
|
||||
return this.$refs.coursepicker?.reload();
|
||||
},
|
||||
isParked(id) {
|
||||
return this.$refs.parking?.isParked(id) ?? false;
|
||||
},
|
||||
park(items) {
|
||||
return this.$refs.parking?.park(null, items);
|
||||
},
|
||||
unpark(item) {
|
||||
return this.$refs.parking?.unpark(item);
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
courseLecturers() {
|
||||
if (!this.lecturers.length) return [];
|
||||
return this.lecturers
|
||||
.filter((lecture) => lecture.showCoursePicker)
|
||||
.map((lecture) => lecture.uid);
|
||||
},
|
||||
},
|
||||
template: /* html */ `
|
||||
<nav
|
||||
id="sidebarMenu"
|
||||
class="bg-light offcanvas offcanvas-start col-md p-md-0 h-100 d-flex flex-column"
|
||||
class="bg-light offcanvas offcanvas-start col-md p-md-0 h-100 w-100"
|
||||
>
|
||||
<div class="sidebar-icons d-flex flex-row align-items-start py-2 gap-1 ps-2">
|
||||
<button
|
||||
@@ -149,12 +166,17 @@ export default {
|
||||
<parking-slot
|
||||
ref="parking"
|
||||
@update:parked-keys="$emit('update:parkedKeys', $event)"
|
||||
@select-kw="$emit('select-kw', $event)"
|
||||
></parking-slot>
|
||||
|
||||
<fhc-coursepicker
|
||||
ref="coursepicker"
|
||||
:studiengaenge="studiengaenge"
|
||||
:studiensemester="selectedStudiensemester"
|
||||
:lecturers="courseLecturers"
|
||||
:preview-lehreinheit-id="raumvorschlagPreview?.lehreinheit_id ?? null"
|
||||
:preview-loading="raumvorschlagLoading"
|
||||
@preview-raumvorschlag="$emit('preview-raumvorschlag', $event)"
|
||||
@select-lecturer="$emit('select-lecturer', $event)"
|
||||
@select-kw="$emit('select-kw', $event)"
|
||||
></fhc-coursepicker>
|
||||
|
||||
@@ -21,7 +21,6 @@ import ApiRenderers from '../../api/factory/renderers.js';
|
||||
import ApiTempusConfig from '../../api/factory/tempus/config.js';
|
||||
import drop from '../../directives/drop.js';
|
||||
import AppConfig from '../AppConfig.js';
|
||||
import ApiStudiengangTree from '../../api/factory/tempus/studiengangtree.js';
|
||||
import ApiInfo from '../../api/factory/tempus/info.js';
|
||||
import Reservierung from './Reservierung.js';
|
||||
import { getTempusShortcuts } from './shortcuts.js';
|
||||
@@ -38,6 +37,7 @@ import TempusVerbandMenu from './VerbandMenu.js';
|
||||
import TempusSidebarMenu from './SidebarMenu.js';
|
||||
import RaumauswahlModal from './RaumauswahlModal.js';
|
||||
import LehreinheitModal from './LehreinheitModal.js';
|
||||
import HorizontalSplit from '../horizontalsplit/horizontalsplit.js';
|
||||
|
||||
export default {
|
||||
name: 'Tempus',
|
||||
@@ -56,6 +56,7 @@ export default {
|
||||
TagsAssignmentModal,
|
||||
RaumauswahlModal,
|
||||
LehreinheitModal,
|
||||
HorizontalSplit,
|
||||
},
|
||||
props: {
|
||||
defaultSemester: String,
|
||||
@@ -93,6 +94,7 @@ export default {
|
||||
deleteEntries: (origList) => this.deleteEntries(origList),
|
||||
openRaumauswahl: (orig) => this.$refs.raumModal.show(orig),
|
||||
},
|
||||
canToggleGrid: this.permissions.stundenraster,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
@@ -100,41 +102,25 @@ export default {
|
||||
appconfig: {},
|
||||
currentMode: 'week',
|
||||
configEndpoints: ApiTempusConfig,
|
||||
endpoint: ApiStudiengangTree,
|
||||
raumVorschlaege: [],
|
||||
selected: [],
|
||||
|
||||
lv_id: null,
|
||||
events: null,
|
||||
minimized: false,
|
||||
currentlySelectedEvent: null,
|
||||
hoveredEvent: null,
|
||||
studiensemesterKurzbz: this.defaultSemester,
|
||||
lists: {
|
||||
nations: [],
|
||||
sprachen: [],
|
||||
geschlechter: [],
|
||||
},
|
||||
renderers: null,
|
||||
renderers: {},
|
||||
ort_kurzbz: null,
|
||||
view: 'room',
|
||||
parkedKeys: new Set(),
|
||||
lecturers: [],
|
||||
studiengaenge: [],
|
||||
rooms: [],
|
||||
overlayCache: [],
|
||||
overlayCache: {},
|
||||
extraBackgrounds: [],
|
||||
lastRange: null,
|
||||
stg: null,
|
||||
semester: null,
|
||||
studiensemester_kurzbz: null,
|
||||
visibleStatusArray: {},
|
||||
visibleStatus: ['all'],
|
||||
selectedStudiensemester:
|
||||
this.studiensemester_kurzbz ?? this.defaultSemester,
|
||||
calendarDate: luxon.DateTime.now()
|
||||
.setZone(this.config.timezone)
|
||||
.toISODate(),
|
||||
selectedStudiensemester: this.defaultSemester,
|
||||
calendarDatesByMode: {
|
||||
week: luxon.DateTime.now().setZone(this.config.timezone).toISODate(),
|
||||
month: luxon.DateTime.now().setZone(this.config.timezone).toISODate(),
|
||||
tableList: luxon.DateTime.now()
|
||||
.setZone(this.config.timezone)
|
||||
.toISODate(),
|
||||
},
|
||||
historyEntries: [],
|
||||
previewRole: 'planer',
|
||||
multiWeekModal: {
|
||||
@@ -145,11 +131,19 @@ export default {
|
||||
endTime: null,
|
||||
},
|
||||
studiengaenge_all: [],
|
||||
raumvorschlagPreview: null,
|
||||
raumvorschlagLoading: false,
|
||||
showEvents: true,
|
||||
reservierungPending: false,
|
||||
bcc: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
currentDay() {
|
||||
return luxon.DateTime.now().setZone(this.config.timezone).toISODate();
|
||||
calendarDate() {
|
||||
return (
|
||||
this.calendarDatesByMode[this.currentMode] ??
|
||||
this.calendarDatesByMode.week
|
||||
);
|
||||
},
|
||||
visibleLecturerUids() {
|
||||
if (!this.lecturers.length) return null;
|
||||
@@ -157,22 +151,6 @@ export default {
|
||||
.filter((lecture) => lecture.showEvents)
|
||||
.map((lecture) => lecture.uid);
|
||||
},
|
||||
visibleStatusOptions() {
|
||||
return Object.entries(this.visibleStatusArray).map(([key, label]) => ({
|
||||
key,
|
||||
label,
|
||||
}));
|
||||
},
|
||||
visibleStatusValue() {
|
||||
if (this.visibleStatus.includes('all'))
|
||||
return this.visibleStatusOptions.filter(
|
||||
(visibleStatus) => visibleStatus.key === 'all',
|
||||
);
|
||||
return this.visibleStatus.map((status) => ({
|
||||
key: status,
|
||||
label: this.visibleStatusArray[status],
|
||||
}));
|
||||
},
|
||||
keyboardShortcuts() {
|
||||
return getTempusShortcuts(this);
|
||||
},
|
||||
@@ -187,6 +165,7 @@ export default {
|
||||
await this.deleteEntryCall(orig);
|
||||
this.$refs.calendar.resetEventLoader();
|
||||
this.$refs.sidebar.reloadCoursepicker();
|
||||
this.rebuildRaumvorschlag();
|
||||
},
|
||||
async deleteEntries(origList) {
|
||||
let validList = (origList ?? []).filter((orig) => orig?.kalender_id);
|
||||
@@ -226,7 +205,80 @@ export default {
|
||||
.call(ApiKalender.syncToStudent(orig.kalender_id))
|
||||
.then(() => this.$refs.calendar.resetEventLoader());
|
||||
},
|
||||
setOrt: function (data) {
|
||||
rebuildRaumvorschlag() {
|
||||
if (!this.raumvorschlagPreview?.lehreinheit_id) return;
|
||||
|
||||
this.previewRaumvorschlag({
|
||||
lehreinheit_id: this.raumvorschlagPreview.lehreinheit_id,
|
||||
});
|
||||
},
|
||||
|
||||
clearRaumvorschlagPreview() {
|
||||
this.raumvorschlagPreview = null;
|
||||
this.raumvorschlagLoading = false;
|
||||
this.rebuildExtraBackgrounds();
|
||||
this.showEvents = true;
|
||||
},
|
||||
async previewRaumvorschlag(orig) {
|
||||
if (!orig?.lehreinheit_id) {
|
||||
this.clearRaumvorschlagPreview();
|
||||
return;
|
||||
}
|
||||
if (!this.lastRange) return;
|
||||
|
||||
const preview = {
|
||||
lehreinheit_id: orig.lehreinheit_id,
|
||||
slots: [],
|
||||
};
|
||||
this.raumvorschlagPreview = preview;
|
||||
this.raumvorschlagLoading = true;
|
||||
|
||||
try {
|
||||
const result = await this.$api.call(
|
||||
ApiKalender.getRaumvorschlagSlots(
|
||||
orig.lehreinheit_id,
|
||||
this.lastRange.start.toISODate(),
|
||||
this.lastRange.end.toISODate(),
|
||||
),
|
||||
);
|
||||
|
||||
if (this.raumvorschlagPreview !== preview) return;
|
||||
|
||||
preview.slots = (result.data ?? []).map((slot) => ({
|
||||
class: `rounded-3 bg-raumvorschlag-slot rating-${slot.rating}`,
|
||||
start: slot.isostart,
|
||||
matchEnd: slot.isoend,
|
||||
end: slot.marker_isoend,
|
||||
label: slot.label,
|
||||
raeume: slot.raeume,
|
||||
}));
|
||||
this.showEvents = preview.slots.length === 0;
|
||||
} catch (error) {
|
||||
if (this.raumvorschlagPreview === preview) this.showEvents = true;
|
||||
this.$fhcAlert.handleSystemError(error);
|
||||
} finally {
|
||||
if (this.raumvorschlagPreview === preview) {
|
||||
this.raumvorschlagLoading = false;
|
||||
this.rebuildExtraBackgrounds();
|
||||
}
|
||||
}
|
||||
},
|
||||
findRaumvorschlagSlot(lehreinheit_id, startDT, endDT) {
|
||||
if (this.raumvorschlagPreview?.lehreinheit_id !== lehreinheit_id)
|
||||
return null;
|
||||
|
||||
return (
|
||||
this.raumvorschlagPreview.slots.find((slot) => {
|
||||
const slotStart = luxon.DateTime.fromISO(slot.start);
|
||||
const slotEnd = luxon.DateTime.fromISO(slot.matchEnd);
|
||||
return (
|
||||
slotStart.toMillis() === startDT.toMillis() &&
|
||||
slotEnd.toMillis() === endDT.toMillis()
|
||||
);
|
||||
}) ?? null
|
||||
);
|
||||
},
|
||||
setOrt(data) {
|
||||
this.ort_kurzbz = data.ort_kurzbz;
|
||||
this.rooms = [{ ort_kurzbz: data.ort_kurzbz }];
|
||||
},
|
||||
@@ -237,7 +289,7 @@ export default {
|
||||
if (verbandMenu)
|
||||
bootstrap.Offcanvas.getOrCreateInstance(verbandMenu).hide();
|
||||
},
|
||||
onSelectVerband({ path, stg_kz, semester, orgform_kurzbz, name }) {
|
||||
onSelectVerband({ stg_kz, semester, orgform_kurzbz, name }) {
|
||||
let exists = this.studiengaenge.some(
|
||||
(stg) =>
|
||||
stg.stg_kz == stg_kz &&
|
||||
@@ -252,25 +304,46 @@ export default {
|
||||
];
|
||||
}
|
||||
},
|
||||
setEmp: function (data) {
|
||||
const uid = data.uid;
|
||||
const label = data.name;
|
||||
setEmp(data) {
|
||||
if (!data?.uid) return;
|
||||
|
||||
for (const lect of this.lecturers) delete this.overlayCache[lect.uid];
|
||||
|
||||
this.lecturers = [
|
||||
{
|
||||
uid,
|
||||
label,
|
||||
uid: data.uid,
|
||||
label: data.name,
|
||||
showEvents: true,
|
||||
overlays: { blocks: true, wishes: true },
|
||||
showCoursePicker: false,
|
||||
},
|
||||
];
|
||||
|
||||
this.$refs.calendar.resetEventLoader();
|
||||
if (this.lastRange) this.handleRange(this.lastRange);
|
||||
},
|
||||
addToFilter: function (filter, type) {
|
||||
addToCoursePicker(data) {
|
||||
const uid = data.uid;
|
||||
let lecturer = this.lecturers.find((lecture) => lecture.uid === uid);
|
||||
|
||||
if (!lecturer) {
|
||||
this.addToFilter(data, 'mitarbeiter');
|
||||
lecturer = this.lecturers.find((lecture) => lecture.uid === uid);
|
||||
|
||||
if (lecturer) {
|
||||
lecturer.overlays = {
|
||||
blocks: false,
|
||||
wishes: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (lecturer) {
|
||||
lecturer.showCoursePicker = true;
|
||||
}
|
||||
},
|
||||
|
||||
addToFilter(filter, type) {
|
||||
if (type === 'ort') {
|
||||
const ort_kurzbz = filter.ort_kurzbz;
|
||||
if (!this.rooms.some((room) => room.ort_kurzbz === ort_kurzbz)) {
|
||||
@@ -279,13 +352,20 @@ export default {
|
||||
} else if (type === 'mitarbeiter') {
|
||||
const uid = filter.uid;
|
||||
const label = filter.name;
|
||||
if (!this.lecturers.some((l) => l.uid === uid)) {
|
||||
|
||||
let lecturer = this.lecturers.find((lecture) => lecture.uid === uid);
|
||||
|
||||
if (!lecturer) {
|
||||
this.lecturers.push({
|
||||
uid,
|
||||
label,
|
||||
showEvents: true,
|
||||
overlays: { blocks: true, wishes: true },
|
||||
showCoursePicker: false,
|
||||
});
|
||||
} else {
|
||||
lecturer.showEvents = true;
|
||||
lecturer.overlays = { blocks: true, wishes: true };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -304,17 +384,32 @@ export default {
|
||||
},
|
||||
{ zone: this.config.timezone },
|
||||
);
|
||||
this.calendarDate = date.toISODate();
|
||||
this.calendarDatesByMode = {
|
||||
...this.calendarDatesByMode,
|
||||
week: date.toISODate(),
|
||||
};
|
||||
this.currentMode = 'week';
|
||||
},
|
||||
handleChangeDate(newDate) {
|
||||
if (newDate && luxon.DateTime.isDateTime(newDate) && newDate.isValid)
|
||||
this.calendarDate = newDate.toISODate();
|
||||
if (!(newDate && luxon.DateTime.isDateTime(newDate) && newDate.isValid))
|
||||
return;
|
||||
|
||||
this.calendarDatesByMode = {
|
||||
...this.calendarDatesByMode,
|
||||
[this.currentMode]: newDate.toISODate(),
|
||||
};
|
||||
},
|
||||
handleChangeMode(newMode, newDate) {
|
||||
if (!newMode) return;
|
||||
|
||||
if (newDate && luxon.DateTime.isDateTime(newDate) && newDate.isValid) {
|
||||
this.calendarDatesByMode = {
|
||||
...this.calendarDatesByMode,
|
||||
[this.currentMode]: newDate.toISODate(),
|
||||
};
|
||||
}
|
||||
|
||||
this.currentMode = newMode;
|
||||
if (newDate && luxon.DateTime.isDateTime(newDate) && newDate.isValid)
|
||||
this.calendarDate = newDate.toISODate();
|
||||
},
|
||||
updateCollision() {
|
||||
this.$api
|
||||
@@ -325,21 +420,6 @@ export default {
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemErrors);
|
||||
},
|
||||
toggleStatus(selected) {
|
||||
if (!selected || selected.length === 0) {
|
||||
this.visibleStatus = ['all'];
|
||||
return;
|
||||
}
|
||||
const hasAll = selected.includes('all');
|
||||
const hadAll = this.visibleStatus.includes('all');
|
||||
|
||||
if (hasAll && !hadAll) {
|
||||
this.visibleStatus = ['all'];
|
||||
return;
|
||||
}
|
||||
this.visibleStatus = selected.filter((k) => k !== 'all');
|
||||
if (this.visibleStatus.length === 0) this.visibleStatus = ['all'];
|
||||
},
|
||||
searchfunction(params) {
|
||||
return this.$api.call(ApiSearchbar.search(params));
|
||||
},
|
||||
@@ -383,51 +463,6 @@ export default {
|
||||
),
|
||||
];
|
||||
},
|
||||
toDateTime(value, timezone) {
|
||||
if (luxon.DateTime.isDateTime(value)) return value;
|
||||
|
||||
if (value?.date?.isValid) return value.date;
|
||||
|
||||
if (typeof value === 'number')
|
||||
return luxon.DateTime.fromMillis(value, { zone: timezone });
|
||||
|
||||
if (value instanceof Date)
|
||||
return luxon.DateTime.fromJSDate(value, { zone: timezone });
|
||||
|
||||
if (typeof value === 'string')
|
||||
return luxon.DateTime.fromISO(value, { zone: timezone });
|
||||
|
||||
return luxon.DateTime.invalid('invalid datetime');
|
||||
},
|
||||
getLastEndOfSameDay(startDT, ends) {
|
||||
if (!ends?.length) return null;
|
||||
|
||||
const dayKey = startDT.toISODate();
|
||||
let lastSameDay = null;
|
||||
|
||||
for (const end of ends) {
|
||||
const dt = luxon.DateTime.isDateTime(end)
|
||||
? end
|
||||
: luxon.DateTime.fromISO(String(end), { zone: startDT.zoneName });
|
||||
|
||||
if (!dt.isValid) continue;
|
||||
|
||||
if (dt.toISODate() === dayKey) lastSameDay = dt;
|
||||
}
|
||||
|
||||
return lastSameDay;
|
||||
},
|
||||
clampEndToGrid(startDT, durationMin, ends) {
|
||||
const calculatedEnd = startDT.plus({ minutes: durationMin });
|
||||
|
||||
const lastGridEndSameDay = this.getLastEndOfSameDay(startDT, ends);
|
||||
|
||||
if (!lastGridEndSameDay) return calculatedEnd;
|
||||
|
||||
return calculatedEnd > lastGridEndSameDay
|
||||
? lastGridEndSameDay
|
||||
: calculatedEnd;
|
||||
},
|
||||
_parseDates(start, end) {
|
||||
const startDT = luxon.DateTime.fromISO(start);
|
||||
const endDT = luxon.DateTime.fromISO(end);
|
||||
@@ -494,6 +529,7 @@ export default {
|
||||
() => {
|
||||
this.$refs.calendar.resetEventLoader();
|
||||
this.$refs.sidebar.reloadCoursepicker();
|
||||
this.rebuildRaumvorschlag();
|
||||
},
|
||||
);
|
||||
},
|
||||
@@ -523,6 +559,8 @@ export default {
|
||||
)
|
||||
.then(() => {
|
||||
this.$refs.calendar.resetEventLoader();
|
||||
this.$refs.sidebar.reloadCoursepicker();
|
||||
this.rebuildRaumvorschlag();
|
||||
this.bcc.postMessage('dropped');
|
||||
});
|
||||
}
|
||||
@@ -546,24 +584,68 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
return this.$api
|
||||
.call(
|
||||
ApiKalender.addKalenderEvent(
|
||||
obj.orig.lehreinheit_id,
|
||||
this.rooms.length
|
||||
? this.rooms.map((r) => r.ort_kurzbz)
|
||||
: (obj.orig.ort_kurzbz ?? []),
|
||||
const matchedSlot = this.findRaumvorschlagSlot(
|
||||
obj.orig.lehreinheit_id,
|
||||
startDT,
|
||||
endDT,
|
||||
);
|
||||
const raeume = matchedSlot?.raeume ?? null;
|
||||
|
||||
start_time,
|
||||
end_time,
|
||||
),
|
||||
)
|
||||
.then((result) => result.data)
|
||||
.then((result) => {
|
||||
this.$refs.calendar.resetEventLoader();
|
||||
this.$refs.sidebar.reloadCoursepicker();
|
||||
this.bcc.postMessage('dropped');
|
||||
});
|
||||
if (!raeume) {
|
||||
return this.$api
|
||||
.call(
|
||||
ApiKalender.addKalenderEvent(
|
||||
obj.orig.lehreinheit_id,
|
||||
this.rooms.length
|
||||
? this.rooms.map((r) => r.ort_kurzbz)
|
||||
: (obj.orig.ort_kurzbz ?? []),
|
||||
start_time,
|
||||
end_time,
|
||||
),
|
||||
)
|
||||
.then((result) => result.data)
|
||||
.then((result) => {
|
||||
if (result.needs_room_selection) {
|
||||
this.$refs.raumModal.showForNew(
|
||||
obj.orig.lehreinheit_id,
|
||||
start_time,
|
||||
end_time,
|
||||
result.raum_vorschlaege,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
this.$refs.calendar.resetEventLoader();
|
||||
this.$refs.sidebar.reloadCoursepicker();
|
||||
this.rebuildRaumvorschlag();
|
||||
this.bcc.postMessage('dropped');
|
||||
});
|
||||
}
|
||||
|
||||
if (raeume.length === 1) {
|
||||
return this.$api
|
||||
.call(
|
||||
ApiKalender.addKalenderEvent(
|
||||
obj.orig.lehreinheit_id,
|
||||
raeume[0].ort_kurzbz,
|
||||
start_time,
|
||||
end_time,
|
||||
),
|
||||
)
|
||||
.then(() => {
|
||||
this.$refs.calendar.resetEventLoader();
|
||||
this.$refs.sidebar.reloadCoursepicker();
|
||||
this.bcc.postMessage('dropped');
|
||||
this.rebuildRaumvorschlag();
|
||||
});
|
||||
}
|
||||
|
||||
this.$refs.raumModal.showForNew(
|
||||
obj.orig.lehreinheit_id,
|
||||
start_time,
|
||||
end_time,
|
||||
raeume,
|
||||
);
|
||||
} else if (obj.type === 'kalender') {
|
||||
return this._updateKalenderEvent(
|
||||
obj,
|
||||
@@ -577,6 +659,7 @@ export default {
|
||||
id: obj.orig.kalender_id,
|
||||
});
|
||||
this.$refs.calendar.resetEventLoader();
|
||||
this.rebuildRaumvorschlag();
|
||||
this.bcc.postMessage('dropped');
|
||||
},
|
||||
);
|
||||
@@ -597,6 +680,7 @@ export default {
|
||||
onMultiWeekConfirmed() {
|
||||
this.$refs.calendar.resetEventLoader();
|
||||
this.$refs.sidebar.reloadCoursepicker();
|
||||
this.rebuildRaumvorschlag();
|
||||
this.bcc.postMessage('dropped');
|
||||
},
|
||||
handleRange(range) {
|
||||
@@ -620,6 +704,11 @@ export default {
|
||||
}
|
||||
|
||||
this.rebuildExtraBackgrounds();
|
||||
|
||||
if (this.raumvorschlagPreview)
|
||||
this.previewRaumvorschlag({
|
||||
lehreinheit_id: this.raumvorschlagPreview.lehreinheit_id,
|
||||
});
|
||||
},
|
||||
|
||||
getOverlays(uid, range, rangeKey) {
|
||||
@@ -706,6 +795,9 @@ export default {
|
||||
if (lect.overlays.wishes) res.push(...(entry.wishes || []));
|
||||
}
|
||||
|
||||
if (this.raumvorschlagPreview)
|
||||
res.push(...this.raumvorschlagPreview.slots);
|
||||
|
||||
this.extraBackgrounds = res;
|
||||
},
|
||||
|
||||
@@ -727,10 +819,14 @@ export default {
|
||||
this.previewRole = role;
|
||||
this.$refs.calendar.resetEventLoader();
|
||||
},
|
||||
openReservierung() {
|
||||
this.reservierungPending = false;
|
||||
this.$refs.reservierung?.show();
|
||||
},
|
||||
triggerSync() {
|
||||
this.$api
|
||||
.call(ApiKalender.sync())
|
||||
.then(this.$refs.calendar.resetEventLoader());
|
||||
.then(() => this.$refs.calendar.resetEventLoader());
|
||||
},
|
||||
onEventHover(event) {
|
||||
this.hoveredEvent = event;
|
||||
@@ -747,7 +843,7 @@ export default {
|
||||
if (this.$refs.sidebar.isParked(event.kalender_id)) {
|
||||
this.$refs.sidebar.unpark({ type: event.type, id: event.kalender_id });
|
||||
} else {
|
||||
this.$refs.sidebar.park(null, {
|
||||
this.$refs.sidebar.park({
|
||||
type: 'kalender',
|
||||
id: event.kalender_id,
|
||||
orig: event,
|
||||
@@ -760,9 +856,6 @@ export default {
|
||||
|
||||
this.deleteEntry(event);
|
||||
},
|
||||
clearHoveredEvent() {
|
||||
this.hoveredEvent = null;
|
||||
},
|
||||
focusSearchbar() {
|
||||
this.$refs.header?.focusSearchbar();
|
||||
},
|
||||
@@ -780,6 +873,7 @@ export default {
|
||||
studiengaenge: {
|
||||
deep: true,
|
||||
handler() {
|
||||
this.clearRaumvorschlagPreview();
|
||||
this.$refs.calendar.resetEventLoader();
|
||||
},
|
||||
},
|
||||
@@ -793,7 +887,7 @@ export default {
|
||||
});
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.bcc.close();
|
||||
this.bcc?.close();
|
||||
},
|
||||
async created() {
|
||||
await this.$api
|
||||
@@ -838,9 +932,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.renderers === null) {
|
||||
this.renderers = {};
|
||||
}
|
||||
if (!this.renderers[rendertype]) {
|
||||
this.renderers[rendertype] = {};
|
||||
}
|
||||
@@ -850,10 +941,6 @@ export default {
|
||||
}
|
||||
});
|
||||
|
||||
this.$api.call(ApiTempusConfig.getHeader()).then((res) => {
|
||||
this.visibleStatusArray = res.data.visible_status;
|
||||
this.visibleStatus = ['all'];
|
||||
});
|
||||
this.$api.call(ApiInfo.getStudiengaenge()).then((res) => {
|
||||
this.studiengaenge_all = res.data;
|
||||
});
|
||||
@@ -871,56 +958,65 @@ export default {
|
||||
:logout-url="logoutUrl"
|
||||
:searchbaroptions="searchbaroptions"
|
||||
:searchfunction="searchfunction"
|
||||
@language-changed="this.$refs.calendar.resetEventLoader();"
|
||||
@language-changed="this.$refs.calendar.resetEventLoader();"
|
||||
/>
|
||||
<div class="container-fluid overflow-hidden heightfull">
|
||||
<div class="row h-100">
|
||||
<tempus-app-menu />
|
||||
<tempus-sidebar-menu
|
||||
ref="sidebar"
|
||||
:preview-role="previewRole"
|
||||
:rooms="rooms"
|
||||
:studiengaenge="studiengaenge"
|
||||
:studiengaenge-all="studiengaenge_all"
|
||||
:lecturers="lecturers"
|
||||
:selected-studiensemester="selectedStudiensemester"
|
||||
@update:preview-role="handlePreviewRoleChange"
|
||||
@update:rooms="rooms = $event"
|
||||
@update:studiengaenge="studiengaenge = $event"
|
||||
@update:parked-keys="parkedKeys = $event"
|
||||
@update:selected-studiensemester="selectedStudiensemester = $event"
|
||||
@remove-lecturer="removeLecturer"
|
||||
@select-lecturer="setEmp"
|
||||
@select-kw="jumpToKw"
|
||||
@sync="triggerSync"
|
||||
/>
|
||||
<main class="col-md-8 ms-sm-auto col-lg-9 col-xl-10">
|
||||
<fhc-calendar
|
||||
ref="calendar"
|
||||
:timezone="config.timezone"
|
||||
:get-promise-func="getPromiseFunc"
|
||||
:visible-status="visibleStatus"
|
||||
:date="calendarDate"
|
||||
:mode="currentMode"
|
||||
:parkedEvents="parkedKeys"
|
||||
:visible-lecturers="visibleLecturerUids"
|
||||
@drop="dropHandler"
|
||||
@resize="resizeHandler"
|
||||
@update:date="handleChangeDate"
|
||||
@update:mode="handleChangeMode"
|
||||
@event-hover="onEventHover"
|
||||
@event-unhover="onEventUnhover"
|
||||
:extra-backgrounds="extraBackgrounds"
|
||||
@update:range="handleRange"
|
||||
class="responsive-calendar"
|
||||
/>
|
||||
</main>
|
||||
|
||||
<horizontal-split :defaultRatio="[15, 85]">
|
||||
<template #left>
|
||||
<tempus-sidebar-menu
|
||||
ref="sidebar"
|
||||
:preview-role="previewRole"
|
||||
:rooms="rooms"
|
||||
:studiengaenge="studiengaenge"
|
||||
:studiengaenge-all="studiengaenge_all"
|
||||
:lecturers="lecturers"
|
||||
:selected-studiensemester="selectedStudiensemester"
|
||||
:raumvorschlag-preview="raumvorschlagPreview"
|
||||
:raumvorschlag-loading="raumvorschlagLoading"
|
||||
@update:preview-role="handlePreviewRoleChange"
|
||||
@update:rooms="rooms = $event"
|
||||
@update:studiengaenge="studiengaenge = $event"
|
||||
@update:parked-keys="parkedKeys = $event"
|
||||
@update:selected-studiensemester="selectedStudiensemester = $event"
|
||||
@remove-lecturer="removeLecturer"
|
||||
@select-lecturer="addToFilter($event, 'mitarbeiter')"
|
||||
@select-kw="jumpToKw"
|
||||
@sync="triggerSync"
|
||||
@preview-raumvorschlag="previewRaumvorschlag"
|
||||
/>
|
||||
</template>
|
||||
<template #right>
|
||||
<fhc-calendar
|
||||
ref="calendar"
|
||||
:timezone="config.timezone"
|
||||
:get-promise-func="getPromiseFunc"
|
||||
:visible-status="visibleStatus"
|
||||
:date="calendarDate"
|
||||
:mode="currentMode"
|
||||
:parkedEvents="parkedKeys"
|
||||
:visible-lecturers="visibleLecturerUids"
|
||||
:show-events="showEvents"
|
||||
@drop="dropHandler"
|
||||
@resize="resizeHandler"
|
||||
@update:date="handleChangeDate"
|
||||
@update:mode="handleChangeMode"
|
||||
@event-hover="onEventHover"
|
||||
@event-unhover="onEventUnhover"
|
||||
@open-reservierung="openReservierung"
|
||||
:extra-backgrounds="extraBackgrounds"
|
||||
@update:range="handleRange"
|
||||
class="responsive-calendar"
|
||||
/>
|
||||
</template>
|
||||
</horizontal-split>
|
||||
</div>
|
||||
</div>
|
||||
<app-config ref="config" v-model="appconfig" :endpoints="configEndpoints"></app-config>
|
||||
<tempus-verband-menu
|
||||
ref="verbandMenu"
|
||||
:endpoint="endpoint"
|
||||
@select-verband-and-close="onSelectVerbandAndClose"
|
||||
/>
|
||||
<raumauswahl-modal ref="raumModal" @saved="$refs.calendar.resetEventLoader()"/>
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
import {CoreFilterCmpt} from '../filter/Filter.js';
|
||||
import {CoreNavigationCmpt} from '../navigation/Navigation.js';
|
||||
import FormInput from "../Form/Input.js";
|
||||
|
||||
import CoreBaseLayout from '../../components/layout/BaseLayout.js';
|
||||
import ApiTempusSync from '../../api/factory/tempus/sync.js';
|
||||
import TempusSyncModal from './Modal.js';
|
||||
import FhcLoader from '../../components/Loader.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
config: Object,
|
||||
defaultSemester: String
|
||||
},
|
||||
components: {
|
||||
CoreFilterCmpt,
|
||||
CoreBaseLayout,
|
||||
CoreNavigationCmpt,
|
||||
FormInput,
|
||||
TempusSyncModal,
|
||||
FhcLoader
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
studiensemester_kurzbz: this.defaultSemester ?? null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
studiensemester_kurzbz()
|
||||
{
|
||||
this.reloadTable();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tabulatorOptions() {
|
||||
return {
|
||||
index: "kalender_syncstatus_id",
|
||||
ajaxURL: 'dummy',
|
||||
ajaxRequestFunc: () => this.$api.call(ApiTempusSync.getSyncs(this.studiensemester_kurzbz)),
|
||||
ajaxResponse: (url, params, response) => {
|
||||
return response.data || [];
|
||||
},
|
||||
layout: 'fitDataStretch',
|
||||
placeholder: "Keine Daten verfügbar",
|
||||
persistenceID: "2026_07_21_tempus_sync_v1",
|
||||
locale: true,
|
||||
columns: [
|
||||
{
|
||||
formatter: 'rowSelection',
|
||||
titleFormatter: 'rowSelection',
|
||||
headerSort: false,
|
||||
width: 40
|
||||
},
|
||||
{titlePhrase: 'lehre/organisationseinheit', field: 'oebezeichnung'},
|
||||
{titlePhrase: 'lehre/studiensemester', field: 'studiensemester_kurzbz'},
|
||||
{titlePhrase: 'lehre/bis_title', field: 'datum_bis',
|
||||
formatter: (cell) => {
|
||||
const value = cell.getValue();
|
||||
if (!value) return ''
|
||||
const date = luxon.DateTime.fromSQL(value)
|
||||
return date.isValid ? date.toFormat('dd.MM.yyyy') : value
|
||||
},
|
||||
minWidth: 100
|
||||
},
|
||||
{titlePhrase: 'lehre/studienplan', field: 'studienplanbezeichnung', minWidth: 200},
|
||||
{titlePhrase: 'lehre/ausbildungssemester', field: 'ausbildungssemester'},
|
||||
{titlePhrase: 'global/status', field: 'sync_status'},
|
||||
{titlePhrase: 'lehre/mail_benachrichtigung', field: 'mail', formatter: 'tickCross', hozAlign: 'center', minWidth: 80},
|
||||
{titlePhrase:'global/insertamum', field: 'insertamum',
|
||||
formatter: (cell) => {
|
||||
const value = cell.getValue();
|
||||
if (!value) return ''
|
||||
const date = luxon.DateTime.fromSQL(value)
|
||||
return date.isValid ? date.toFormat('dd.MM.yyyy HH:mm') : value
|
||||
},
|
||||
visible: false
|
||||
},
|
||||
{titlePhrase: 'global/insertvon', field: 'insertvon', visible: false},
|
||||
{titlePhrase: 'global/updateamum', field: 'updateamum',
|
||||
formatter: (cell) => {
|
||||
const value = cell.getValue();
|
||||
if (!value) return ''
|
||||
const date = luxon.DateTime.fromSQL(value)
|
||||
return date.isValid ? date.toFormat('dd.MM.yyyy HH:mm') : value
|
||||
},
|
||||
visible: false
|
||||
},
|
||||
{titlePhrase: 'global/updatevon', field: 'updatevon', visible: false},
|
||||
{
|
||||
titlePhrase: 'global/aktionen',
|
||||
field: 'actions',
|
||||
headerSort: false,
|
||||
hozAlign: 'center',
|
||||
width: 120,
|
||||
formatter: (cell) => {
|
||||
let container = document.createElement('div');
|
||||
container.className = 'd-flex gap-3';
|
||||
|
||||
const editButton = document.createElement('button');
|
||||
editButton.className = 'btn btn-outline-secondary';
|
||||
editButton.innerHTML = '<i class="fa fa-edit"></i>';
|
||||
editButton.addEventListener('click', () => {
|
||||
this.$refs.syncModal.openEdit(cell.getRow().getData());
|
||||
});
|
||||
container.append(editButton);
|
||||
|
||||
|
||||
const startButton = document.createElement('button');
|
||||
startButton.className = 'btn btn-outline-secondary';
|
||||
startButton.innerHTML = '<i class="fa fa-play"></i>';
|
||||
|
||||
startButton.addEventListener('click', () => {
|
||||
startButton.disabled = true;
|
||||
this.$refs.loader.show();
|
||||
|
||||
this.$refs.syncModal
|
||||
.start(cell.getRow().getData())
|
||||
.then(() => {
|
||||
startButton.disabled = false;
|
||||
this.$refs.loader.hide();
|
||||
|
||||
})
|
||||
.catch(() => {
|
||||
this.$refs.loader.hide();
|
||||
startButton.disabled = false;
|
||||
});
|
||||
});
|
||||
|
||||
container.append(startButton);
|
||||
|
||||
|
||||
const deleteButton = document.createElement('button');
|
||||
deleteButton.className = 'btn btn-outline-secondary';
|
||||
deleteButton.innerHTML = '<i class="fa fa-trash"></i>';
|
||||
|
||||
deleteButton.addEventListener('click', evt => {
|
||||
evt.stopPropagation();
|
||||
this.$fhcAlert
|
||||
.confirmDelete()
|
||||
.then(result =>
|
||||
result
|
||||
? cell.getData().kalender_syncstatus_id
|
||||
: Promise.reject({ handled: true })
|
||||
)
|
||||
.then(kalender_syncstatus_id =>
|
||||
this.$api.call(ApiTempusSync.delete(kalender_syncstatus_id))
|
||||
)
|
||||
.then(() => {
|
||||
this.reloadTable();
|
||||
})
|
||||
.catch(this.$fhcAlert.handleSystemError);
|
||||
});
|
||||
container.append(deleteButton);
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
openNewModal()
|
||||
{
|
||||
this.$refs.syncModal.openNew();
|
||||
},
|
||||
reloadTable()
|
||||
{
|
||||
this.$refs.syncTable.reloadTable();
|
||||
},
|
||||
openStartModal()
|
||||
{
|
||||
this.$refs.syncModal.openStart();
|
||||
},
|
||||
onSaved(studiensemester_kurzbz)
|
||||
{
|
||||
if (studiensemester_kurzbz && studiensemester_kurzbz !== this.studiensemester_kurzbz)
|
||||
{
|
||||
this.studiensemester_kurzbz = studiensemester_kurzbz;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.reloadTable();
|
||||
}
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<core-navigation-cmpt></core-navigation-cmpt>
|
||||
<core-base-layout>
|
||||
<template #main>
|
||||
<fhc-loader ref="loader" :timeout="0"></fhc-loader>
|
||||
|
||||
<core-filter-cmpt
|
||||
ref="syncTable"
|
||||
:tabulator-options="tabulatorOptions"
|
||||
:table-only=true
|
||||
:side-menu="false"
|
||||
:reload="true"
|
||||
:useSelectionSpan="false"
|
||||
new-btn-label="Hinzufügen"
|
||||
new-btn-show
|
||||
@click:new="openNewModal">
|
||||
|
||||
<template #actions>
|
||||
<form-input
|
||||
type="select"
|
||||
v-model="studiensemester_kurzbz"
|
||||
name="studiensemester_kurzbz"
|
||||
>
|
||||
<option :value="null" disabled>-- {{ $p.t('lehre', 'studiensemester') }} --</option>
|
||||
<option value="all">{{ $p.t('ui', 'alleAnzeigen') }}</option>
|
||||
<option
|
||||
v-for="studiensemester in config.studiensemestern"
|
||||
:key="studiensemester.studiensemester_kurzbz"
|
||||
:value="studiensemester.studiensemester_kurzbz"
|
||||
>
|
||||
{{ studiensemester.studiensemester_kurzbz }}
|
||||
</option>
|
||||
</form-input>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-secondary"
|
||||
@click="openStartModal"
|
||||
>
|
||||
{{ $p.t('global', 'jetztStarten') }}
|
||||
</button>
|
||||
</template>
|
||||
|
||||
</core-filter-cmpt>
|
||||
|
||||
<tempus-sync-modal
|
||||
ref="syncModal"
|
||||
:config="config"
|
||||
:stsem_kurzbz="studiensemester_kurzbz"
|
||||
@saved="onSaved"
|
||||
>
|
||||
</tempus-sync-modal>
|
||||
</template>
|
||||
</core-base-layout>
|
||||
|
||||
`
|
||||
};
|
||||
@@ -5,12 +5,6 @@ export default {
|
||||
components: {
|
||||
BaseTreemenu,
|
||||
},
|
||||
props: {
|
||||
endpoint: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: ['select-verband-and-close'],
|
||||
methods: {
|
||||
onSelectVerbandAndClose(payload) {
|
||||
|
||||
@@ -106,6 +106,10 @@ require_once('dbupdate_3.4/75959_StudVw_Automatische_Tags.php');
|
||||
require_once('dbupdate_3.4/76160_lvv_favorites.php');
|
||||
require_once('dbupdate_3.4/77080_tabulator_presets_table.php');
|
||||
require_once('dbupdate_3.4/78292_gehaltsanpassungtyp.php');
|
||||
require_once('dbupdate_3.4/77949_tempus_synchronisation.php');
|
||||
require_once('dbupdate_3.4/78287_tempus_raumzuordnung.php');
|
||||
|
||||
require_once('dbupdate_3.4/78285_tempus_stundenraster.php');
|
||||
|
||||
// *** Pruefung und hinzufuegen der neuen Attribute und Tabellen
|
||||
echo '<H2>Pruefe Tabellen und Attribute!</H2>';
|
||||
|
||||
@@ -249,3 +249,32 @@ if ($result = @$db->db_query("SELECT 1 FROM public.tbl_variablenname WHERE name
|
||||
echo 'public.tbl_variablenname: Added name "tempus_favorites"<br>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!$result = @$db->db_query("SELECT status_kurzbz_max FROM lehre.tbl_kalender LIMIT 1"))
|
||||
{
|
||||
$qry = "ALTER TABLE lehre.tbl_kalender ADD COLUMN status_kurzbz_max character varying(32);
|
||||
|
||||
UPDATE lehre.tbl_kalender_status
|
||||
SET status_kurzbz = 'to_delete',
|
||||
bezeichnung = 'to_delete'
|
||||
WHERE status_kurzbz = 'todelete';
|
||||
UPDATE lehre.tbl_kalender_status SET sort = 9 WHERE status_kurzbz = 'deleted';
|
||||
UPDATE lehre.tbl_kalender_status SET sort = 10 WHERE status_kurzbz = 'archived';
|
||||
INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung, bezeichnung_mehrsprachig, sort) VALUES (E'to_delete_preview', E'to_delete_preview', E'{\"Zur Löschung in Voransicht\", \"Marked for Deletion in Preview\"}', 7);
|
||||
INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung, bezeichnung_mehrsprachig, sort) VALUES (E'to_delete_live', E'to_delete_live', E'{\"Zur Löschung in Live\", \"Marked for Deletion in Live\"}', 8);
|
||||
|
||||
ALTER TABLE lehre.tbl_kalender ADD CONSTRAINT tbl_kalender_status_max_fk FOREIGN KEY (status_kurzbz_max)
|
||||
REFERENCES lehre.tbl_kalender_status (status_kurzbz) MATCH FULL ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
";
|
||||
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_kalender: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br />lehre.tbl_kalender: Spalte status_kurzbz_max hinzugefuegt.
|
||||
<br />lehre.tbl_kalender_status: status_kurzbz von todelete auf to_delete umbenannt.
|
||||
<br />lehre.tbl_kalender_status: status_kurzbz to_delete_preview hinzugefuegt.
|
||||
<br />lehre.tbl_kalender_status: status_kurzbz to_delete_live hinzugefuegt.
|
||||
';
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
if (! defined('DB_NAME')) exit('No direct script access allowed');
|
||||
|
||||
if(!$result = @$db->db_query("SELECT kalender_syncstatus_id FROM lehre.tbl_kalender_syncstatus LIMIT 1"))
|
||||
{
|
||||
$qry = "CREATE TABLE lehre.tbl_kalender_syncstatus
|
||||
(
|
||||
kalender_syncstatus_id bigserial NOT NULL,
|
||||
oe_kurzbz character varying(32),
|
||||
studiensemester_kurzbz character varying(32),
|
||||
datum_bis date,
|
||||
studienplan_id integer,
|
||||
ausbildungssemester smallint,
|
||||
sync_status_kurzbz character varying(32),
|
||||
mail boolean DEFAULT false NOT NULL,
|
||||
insertamum timestamp DEFAULT now(),
|
||||
insertvon character varying(32),
|
||||
updateamum timestamp,
|
||||
updatevon character varying(32),
|
||||
CONSTRAINT tbl_kalender_syncstatus_pk PRIMARY KEY (kalender_syncstatus_id)
|
||||
);
|
||||
|
||||
ALTER TABLE lehre.tbl_kalender_syncstatus ADD CONSTRAINT tbl_kalender_syncstatus_oe_kurzbz_fk FOREIGN KEY (oe_kurzbz) REFERENCES public.tbl_organisationseinheit (oe_kurzbz) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE lehre.tbl_kalender_syncstatus ADD CONSTRAINT tbl_kalender_syncstatus_studiensemester_kurzbz_fk FOREIGN KEY (studiensemester_kurzbz) REFERENCES public.tbl_studiensemester(studiensemester_kurzbz) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE lehre.tbl_kalender_syncstatus ADD CONSTRAINT tbl_kalender_syncstatus_studienplan_id_fk FOREIGN KEY (studienplan_id) REFERENCES lehre.tbl_studienplan (studienplan_id) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
ALTER TABLE lehre.tbl_kalender_syncstatus ADD CONSTRAINT tbl_kalender_syncstatus_status_sync_status_kurzbz_fk FOREIGN KEY (sync_status_kurzbz) REFERENCES lehre.tbl_kalender_status (status_kurzbz) ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
GRANT SELECT, UPDATE ON lehre.tbl_kalender_syncstatus_kalender_syncstatus_id_seq TO vilesci;
|
||||
GRANT SELECT ON lehre.tbl_kalender_syncstatus_kalender_syncstatus_id_seq TO web;
|
||||
GRANT SELECT, UPDATE, INSERT, DELETE ON lehre.tbl_kalender_syncstatus to vilesci;
|
||||
GRANT SELECT ON lehre.tbl_kalender_typ to web;";
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_kalender_syncstatus: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo ' lehre.tbl_kalender_syncstatus: Tabelle hinzugefuegt<br>';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
if (! defined('DB_NAME')) exit('No direct script access allowed');
|
||||
|
||||
if($result = $db->db_query("SELECT * FROM system.tbl_berechtigung WHERE berechtigung_kurzbz='basis/tempus_stundenraster'"))
|
||||
{
|
||||
if($db->db_num_rows($result)==0)
|
||||
{
|
||||
$qry = "INSERT INTO system.tbl_berechtigung(berechtigung_kurzbz, beschreibung)
|
||||
VALUES('basis/tempus_stundenraster','Berechtigung, um den Stundenraster zu aktivieren/deaktivieren');";
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>Berechtigung: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo 'Neue Berechtigung basis/tempus_stundenraster hinzugefuegt!<br>';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
if (! defined('DB_NAME')) exit('No direct script access allowed');
|
||||
|
||||
if ($result = @$db->db_query("SELECT 1 FROM public.tbl_variablenname WHERE name = 'roomless_planning';"))
|
||||
{
|
||||
if ($db->db_num_rows($result) == 0)
|
||||
{
|
||||
$qry = "INSERT INTO public.tbl_variablenname(name, defaultwert) VALUES('roomless_planning', false);
|
||||
INSERT INTO public.tbl_variablenname(name, defaultwert) VALUES('priority_room_planning', false);
|
||||
INSERT INTO public.tbl_variablenname(name, defaultwert) VALUES('dialog_room_planning', false);";
|
||||
|
||||
if (!$db->db_query($qry))
|
||||
echo '<strong>public.tbl_variablenname '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo 'public.tbl_variablenname: Added "roomless_planning", "priority_room_planning", "dialog_room_planning"<br>';
|
||||
}
|
||||
}
|
||||
@@ -3363,6 +3363,126 @@ $phrases = array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'lehre',
|
||||
'phrase' => 'mail_benachrichtigung',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Mail-Benachrichtigung',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Email notification',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'lehre',
|
||||
'phrase' => 'bis_title',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Bis',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Until',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'lehre',
|
||||
'phrase' => 'errorDeleting',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Fehler beim Löschen.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Error deleting.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'lehre',
|
||||
'phrase' => 'tempus_sync_start',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Synchronisierung manuell starten',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Start synchronization manually',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'lehre',
|
||||
'phrase' => 'tempus_sync_edit',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Sync-Eintrag bearbeiten',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Edit sync entry',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'lehre',
|
||||
'phrase' => 'tempus_sync_new',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Neuer Sync-Eintrag',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'New sync entry',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'lehre',
|
||||
@@ -37385,6 +37505,86 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'roomless_planning_error',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Raumloseplanung deaktiviert',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Roomless planning is disabled.',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'roomless_planning',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Raumlos planen',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Plan without room',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'priority_room_planning',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => ' Prioritätsraum verwenden',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Use priority room',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'dialog_room_planning',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Raumauswahl anzeigen',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Show room selection',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'softwarebereitstellung',
|
||||
'category' => 'ui',
|
||||
@@ -39128,6 +39328,26 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
'phrase' => 'successStart',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => '"Erfolgreich gestartet',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Started successfully',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'ui',
|
||||
|
||||
Reference in New Issue
Block a user