mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 12:19:28 +00:00
Erster Prototyp für Tempus Neu DB und GUI
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Tempus extends Auth_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$permissions = [];
|
||||
$router = load_class('Router');
|
||||
$permissions[$router->method] = ['admin:r', 'assistenz:r'];
|
||||
parent::__construct($permissions);
|
||||
|
||||
// Load Libraries
|
||||
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
|
||||
|
||||
// Load Config
|
||||
$this->load->config('calendar');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function _remap()
|
||||
{
|
||||
|
||||
$this->load->view('Tempus', [
|
||||
'permissions' => [
|
||||
'admin' => $this->permissionlib->isBerechtigt('admin')
|
||||
],
|
||||
'variables' => [
|
||||
'semester_aktuell' => $this->variablelib->getVar('semester_aktuell'),
|
||||
'timezone' => $this->config->item('timezone')
|
||||
]
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class Kalender extends FHCAPI_Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Object initialization
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
parent::__construct([
|
||||
'getRoomplan' => self::PERM_LOGGED,
|
||||
'Stunden' => self::PERM_LOGGED,
|
||||
'Reservierungen' => self::PERM_LOGGED,
|
||||
'getStundenplan' => self::PERM_LOGGED,
|
||||
'getLehreinheitStudiensemester' => self::PERM_LOGGED,
|
||||
'updateKalenderEvent' => 'lehre/lvplan:rw',
|
||||
'addKalenderEvent' => 'lehre/lvplan:rw'
|
||||
]);
|
||||
|
||||
$this->load->library('LogLib');
|
||||
$this->loglib->setConfigs(array(
|
||||
'classIndex' => 5,
|
||||
'functionIndex' => 5,
|
||||
'lineIndex' => 4,
|
||||
'dbLogType' => 'API', // required
|
||||
'dbExecuteUser' => 'RESTful API'
|
||||
));
|
||||
|
||||
$this->uid = getAuthUID();
|
||||
|
||||
$this->load->library('form_validation');
|
||||
|
||||
//load models
|
||||
//$this->load->model('ressource/Stundenplan_model', 'StundenplanModel');
|
||||
//$this->load->model('ressource/Reservierung_model', 'ReservierungModel');
|
||||
|
||||
$this->load->library('KalenderLib');
|
||||
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* fetches Stunden layout from database
|
||||
* @access public
|
||||
*
|
||||
*/
|
||||
public function Stunden()
|
||||
{
|
||||
$this->load->model('ressource/Stunde_model', 'StundeModel');
|
||||
|
||||
$stunden = $this->StundeModel->load();
|
||||
|
||||
$stunden = $this->getDataOrTerminateWithError($stunden);
|
||||
|
||||
$this->terminateWithSuccess($stunden);
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches stundenplan events from a Room and start/end date
|
||||
* @access public
|
||||
*
|
||||
*/
|
||||
public function getRoomplan()
|
||||
{
|
||||
|
||||
// form validation
|
||||
$this->load->library('form_validation');
|
||||
$this->form_validation->set_data($_GET);
|
||||
$this->form_validation->set_rules('start_date',"start_date","required");
|
||||
$this->form_validation->set_rules('end_date',"end_date","required");
|
||||
$this->form_validation->set_rules('ort_kurzbz',"ort_kurzbz","required");
|
||||
if($this->form_validation->run() === FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
// storing the get parameter in local variables
|
||||
$start_date = $this->input->get('start_date', TRUE);
|
||||
$end_date = $this->input->get('end_date', TRUE);
|
||||
$ort_kurzbz = $this->input->get('ort_kurzbz', TRUE);
|
||||
|
||||
$stundenplan_data =$this->kalenderlib->getRoomData($ort_kurzbz, $start_date, $end_date);
|
||||
|
||||
$this->terminateWithSuccess($stundenplan_data);
|
||||
}
|
||||
|
||||
public function updateKalenderEvent()
|
||||
{
|
||||
// form validation
|
||||
$this->load->library('form_validation');
|
||||
$this->form_validation->set_data($_POST);
|
||||
$this->form_validation->set_rules('kalender_id',"kalender_id","required");
|
||||
$this->form_validation->set_rules('ort_kurzbz',"ort_kurzbz","required");
|
||||
$this->form_validation->set_rules('start_date',"start_date","required");
|
||||
$this->form_validation->set_rules('end_date',"end_date","optional");
|
||||
|
||||
if($this->form_validation->run() === FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
// storing the get parameter in local variables
|
||||
$kalender_id = $this->input->post('kalender_id', TRUE);
|
||||
$ort_kurzbz = $this->input->post('ort_kurzbz', TRUE);
|
||||
$start_date = $this->input->post('start_date', TRUE);
|
||||
$end_date = $this->input->post('end_date', TRUE);
|
||||
|
||||
|
||||
// Was passiert hier?
|
||||
// Raumänderung, Tagesänderung, Start / Ende Zeit korrektur
|
||||
// Ist das alles ein Endpunkt?
|
||||
$stundenplan_data =$this->kalenderlib->updateKalenderEvent($this->uid,$kalender_id, $ort_kurzbz, $start_date, $end_date);
|
||||
|
||||
$this->terminateWithSuccess($stundenplan_data);
|
||||
}
|
||||
|
||||
public function addKalenderEvent()
|
||||
{
|
||||
// form validation
|
||||
$this->load->library('form_validation');
|
||||
$this->form_validation->set_data($_POST);
|
||||
$this->form_validation->set_rules('lehreinheit_id',"kalender_id","required");
|
||||
$this->form_validation->set_rules('ort_kurzbz',"ort_kurzbz","required");
|
||||
$this->form_validation->set_rules('start_date',"start_date","required");
|
||||
$this->form_validation->set_rules('end_date',"end_date","required");
|
||||
|
||||
if($this->form_validation->run() === FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
// storing the get parameter in local variables
|
||||
$lehreinheit_id = $this->input->post('lehreinheit_id', TRUE);
|
||||
$ort_kurzbz = $this->input->post('ort_kurzbz', TRUE);
|
||||
$start_date = $this->input->post('start_date', TRUE);
|
||||
$end_date = $this->input->post('end_date', TRUE);
|
||||
|
||||
$this->kalenderlib->addKalenderEvent($this->uid, $ort_kurzbz, $start_date, $end_date, $lehreinheit_id);
|
||||
|
||||
$this->terminateWithSuccess();
|
||||
}
|
||||
|
||||
// gets the reservierungen of a room if the ort_kurzbz parameter is supplied otherwise gets the reservierungen of the stundenplan of a student
|
||||
public function Reservierungen($ort_kurzbz = null)
|
||||
{
|
||||
$this->terminateWithSuccess();
|
||||
}
|
||||
|
||||
public function getLehreinheitStudiensemester($lehreinheit_id)
|
||||
{
|
||||
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
|
||||
$this->LehreinheitModel->addSelect(["studiensemester_kurzbz"]);
|
||||
$result = $this->LehreinheitModel->load($lehreinheit_id);
|
||||
$result = current($this->getDataOrTerminateWithError($result))->studiensemester_kurzbz;
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class Tempus extends FHCAPI_Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Object initialization
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
parent::__construct([
|
||||
'getCourses' => self::PERM_LOGGED,
|
||||
]);
|
||||
|
||||
$this->load->library('LogLib');
|
||||
$this->loglib->setConfigs(array(
|
||||
'classIndex' => 5,
|
||||
'functionIndex' => 5,
|
||||
'lineIndex' => 4,
|
||||
'dbLogType' => 'API', // required
|
||||
'dbExecuteUser' => 'RESTful API'
|
||||
));
|
||||
|
||||
$this->load->library('form_validation');
|
||||
|
||||
//load models
|
||||
//$this->load->model('ressource/Stundenplan_model', 'StundenplanModel');
|
||||
//$this->load->model('ressource/Reservierung_model', 'ReservierungModel');
|
||||
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
|
||||
/**
|
||||
* fetches courses
|
||||
* @access public
|
||||
*
|
||||
*/
|
||||
public function getCourses()
|
||||
{
|
||||
// form validation
|
||||
$this->load->library('form_validation');
|
||||
$this->form_validation->set_data($_GET);
|
||||
$this->form_validation->set_rules('searchfilter',"searchfilter","required");
|
||||
if($this->form_validation->run() === FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
|
||||
|
||||
// storing the get parameter in local variables
|
||||
$searchfilter = $this->input->get('searchfiler', TRUE);
|
||||
|
||||
// TODO implement Loading Data
|
||||
$course_data = array(
|
||||
array(
|
||||
'lehreinheit_id'=>'1',
|
||||
'bezeichnung' => 'Englisch 1',
|
||||
'studiengang_kurzbz' => 'BMR',
|
||||
'semester' => '1',
|
||||
'kurzbz' => 'ENG',
|
||||
'lektoren' => array('OesterAn','KindlMa')
|
||||
),
|
||||
array(
|
||||
'lehreinheit_id'=>'2',
|
||||
'bezeichnung' => 'Mahtematik 1',
|
||||
'studiengang_kurzbz' => 'BMR',
|
||||
'semester' => '1',
|
||||
'kurzbz' => 'MAT',
|
||||
'lektoren' => array('BamberHa')
|
||||
)
|
||||
);
|
||||
|
||||
$this->terminateWithSuccess($course_data);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
/*
|
||||
* Job zur einmaligen Migration des Stundenplans
|
||||
*
|
||||
* Aufruf
|
||||
* php index.ci.php system/MigrateKalender
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class MigrateKalender extends CLI_Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->load->model('ressource/Kalender_model', 'KalenderModel');
|
||||
$this->load->model('ressource/Kalender_Lehreinheit_model', 'KalenderLehreinheitModel');
|
||||
$this->load->model('ressource/Kalender_Ort_model', 'KalenderOrtModel');
|
||||
$this->load->model('ressource/Stundenplandev_Kalender_model', 'SyncModel');
|
||||
}
|
||||
|
||||
/**
|
||||
* Everything has a beginning
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$von = date('Y-m-d') // TODO
|
||||
$bis = date('Y-m-d') // TODO
|
||||
|
||||
$db = new DB_Model();
|
||||
$stpldevsql = '
|
||||
SELECT *,
|
||||
(SELECT beginn FROM lehre.tbl_stunde WHERE stunde=tbl_stundenplandev.stunde) as beginn,
|
||||
(SELECT ende FROM lehre.tbl_stunde WHERE stunde=tbl_stundenplandev.stunde) as ende
|
||||
FROM
|
||||
lehre.tbl_stundenplandev WHERE datum>=? and datum<=? ORDER BY datum, stunde, unr';
|
||||
|
||||
$stpldev = $db->execReadOnlyQuery($stpldevsql, array($von, $bis));
|
||||
if (hasData($stpldev))
|
||||
{
|
||||
// Pruefen ob der Eintrag schon in Sync Tabelle vorhanden ist
|
||||
// Wenn neuere Änderungen vorhanden dann Update
|
||||
// Wenn keine Änderungen seit leztem Sync dann Ueberspringen
|
||||
// Wenn noch nicht vorhanden neu anlegen
|
||||
// Danach ggf pruefen welceh Eintraege in der zwischenzeit geloescht wurden und
|
||||
// in der neuen Tabelle auch archivieren oder loeschen
|
||||
|
||||
$data = getData($stpldev);
|
||||
foreach($data as $rowstpl)
|
||||
{
|
||||
$SyncResult = $this->SyncModel->loadWhere(
|
||||
array('stundenplandev_id' => $rowstpl->stundenplandev_id)
|
||||
);
|
||||
if(hasData($SyncResult))
|
||||
{
|
||||
//bereits vorhanden
|
||||
// TODO Update
|
||||
}
|
||||
else
|
||||
{
|
||||
// Neuen Eintrag anlegen
|
||||
|
||||
$von = $rowstpl->datum.' '.$rowstpl->beginn;
|
||||
$bis = $rowstpl->datum.' '.$rowstpl->ende;
|
||||
$typ = 'lehreinheit';
|
||||
$status = 'visible_student';
|
||||
$insertamum = $rowstpl->insertamum;
|
||||
$insertvon = $rowstpl->insertvon;
|
||||
$updateamum = $rowstpl->updateamum;
|
||||
$updatevon = $rowstpl->updatevon;
|
||||
|
||||
$resultKalenderInsert = $this->KalenderModel->insert(
|
||||
array(
|
||||
'von' => $von,
|
||||
'bis' => $bis,
|
||||
'typ' => $typ,
|
||||
'status_kurzbz' => $status,
|
||||
'vorgaenger_kalender_id' => null,
|
||||
'insertamum' => $insertamum,
|
||||
'insertvon' => $insertvon,
|
||||
'updateamum' => $updateamum,
|
||||
'updatevon' => $updatevon
|
||||
)
|
||||
);
|
||||
|
||||
if(isSuccess($resultKalenderInsert))
|
||||
{
|
||||
$kalender_id = getData($resultKalenderInsert);
|
||||
|
||||
$resultKalenderInsert = $this->KalenderLehreinheitModel->insert(
|
||||
array(
|
||||
'kalender_id' => $kalender_id,
|
||||
'lehreinheit_id' => $rowstpl->lehreinheit_id,
|
||||
)
|
||||
);
|
||||
|
||||
$resultKalenderInsert = $this->KalenderOrtModel->insert(
|
||||
array(
|
||||
'kalender_id' => $kalender_id,
|
||||
'ort_kurzbz' => $rowstpl->ort_kurzbz,
|
||||
)
|
||||
);
|
||||
|
||||
$resultSyncInsert = $this->SyncModel->insert(
|
||||
array(
|
||||
'stundenplandev_id' => $rowstpl->stundenplandev_id,
|
||||
'kalender_id' => $kalender_id,
|
||||
'lastupdate' => date('Y-m-d H:i:s')
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
if (! defined("BASEPATH")) exit("No direct script access allowed");
|
||||
|
||||
class KalenderLib
|
||||
{
|
||||
/**
|
||||
* Loads model OrganisationseinheitModel
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->ci =& get_instance();
|
||||
|
||||
$this->ci->load->model('ressource/Kalender_model', 'KalenderModel');
|
||||
$this->ci->load->model('ressource/Kalender_Lehreinheit_model', 'KalenderLehreinheitModel');
|
||||
$this->ci->load->model('ressource/Kalender_Ort_model', 'KalenderOrtModel');
|
||||
$this->ci->load->model('education/Lehreinheit_model', 'LehreinheitModel');
|
||||
$this->ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
|
||||
$this->ci->load->model('education/LehreinheitMitarbeiter_model', 'LehreinheitMitarbeiterModel');
|
||||
|
||||
}
|
||||
|
||||
public function getRoomData($ort_kurzbz, $start_date, $end_date)
|
||||
{
|
||||
$data = $this->ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'kalender_id');
|
||||
$data = $this->ci->KalenderModel->loadWhere(array(
|
||||
'von >=' => $start_date,
|
||||
'bis <= '=>$end_date,
|
||||
'ort_kurzbz'=>$ort_kurzbz
|
||||
));
|
||||
|
||||
$stundenplan_data = array();
|
||||
if(isSuccess($data) && hasData($data))
|
||||
{
|
||||
$data = getData($data);
|
||||
foreach($data as $rowstpl)
|
||||
{
|
||||
$obj = new stdClass();
|
||||
$obj->type='lehreinheit';
|
||||
|
||||
$von = new DateTime($rowstpl->von);
|
||||
$bis = new DateTime($rowstpl->bis);
|
||||
|
||||
$obj->beginn = $von->format('H:i:s');
|
||||
$obj->ende = $bis->format('H:i:s');
|
||||
$obj->datum = $von->format('Y-m-d');
|
||||
$obj->topic = 'undefined';
|
||||
$obj->lektor = array();
|
||||
$obj->gruppe = array();
|
||||
$obj->isostart = $von->format('c');
|
||||
$obj->isoend = $bis->format('c');
|
||||
$obj->tooltip = 'tip';
|
||||
|
||||
$obj->lehreinheit_id = array();
|
||||
|
||||
$lehreinheiten = $this->ci->KalenderLehreinheitModel->loadWhere(array('kalender_id'=>$rowstpl->kalender_id));
|
||||
if(isSuccess($lehreinheiten) && hasData($lehreinheiten))
|
||||
{
|
||||
$lehreinheiten = getData($lehreinheiten);
|
||||
foreach($lehreinheiten as $le)
|
||||
{
|
||||
$obj->lehreinheit_id[] = $le->lehreinheit_id;
|
||||
|
||||
$lehreinheitdata = $this->ci->LehreinheitModel->loadWhere(array('lehreinheit_id'=>$le->lehreinheit_id));
|
||||
|
||||
if(isSuccess($lehreinheitdata) && hasData($lehreinheitdata))
|
||||
{
|
||||
$ledata = getData($lehreinheitdata)[0];
|
||||
|
||||
|
||||
$lvid = $ledata->lehrveranstaltung_id;
|
||||
$lehrfach_id = $ledata->lehrfach_id;
|
||||
$obj->lehrform = $ledata->lehrform_kurzbz;
|
||||
|
||||
$lehreinheitmitarbeiterdata = $this->ci->LehreinheitMitarbeiterModel->loadWhere(array('lehreinheit_id'=>$le->lehreinheit_id));
|
||||
$lemitarbeiterdata = getData($lehreinheitmitarbeiterdata);
|
||||
|
||||
foreach($lemitarbeiterdata as $rowma)
|
||||
{
|
||||
$obj->lektor[] = array(
|
||||
"mitarbeiter_uid"=> $rowma->mitarbeiter_uid,
|
||||
"vorname"=>$rowma->mitarbeiter_uid,
|
||||
"nachname"=>$rowma->mitarbeiter_uid,
|
||||
"kurzbz"=>$rowma->mitarbeiter_uid
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$lehrfachdata = $this->ci->LehrveranstaltungModel->loadWhere(array('lehrveranstaltung_id' => $lehrfach_id));
|
||||
$lfdata = getData($lehrfachdata)[0];
|
||||
|
||||
$lehrveranstaltungdata = $this->ci->LehrveranstaltungModel->loadWhere(array('lehrveranstaltung_id' => $lvid));
|
||||
$lvdata = getData($lehrveranstaltungdata)[0];
|
||||
|
||||
$obj->topic = $lfdata->kurzbz.' '.$obj->lehrform;
|
||||
|
||||
$orte = $this->ci->KalenderOrtModel->loadWhere(array('kalender_id'=>$rowstpl->kalender_id));
|
||||
$obj->ort_kurzbz = '';
|
||||
if(isSuccess($orte) && hasData($orte))
|
||||
{
|
||||
$ortedata = getdata($orte);
|
||||
foreach($ortedata as $ort);
|
||||
{
|
||||
$obj->ort_kurzbz .= $ort->ort_kurzbz;
|
||||
}
|
||||
}
|
||||
$obj->titel = '';
|
||||
$obj->lehrfach = $lfdata->kurzbz;
|
||||
$obj->lehrfach_bez = $lfdata->bezeichnung;
|
||||
$obj->organisationseinheit = $lvdata->oe_kurzbz;
|
||||
$obj->farbe = $lfdata->farbe;
|
||||
$obj->lehrveranstaltung_id = $lvid;
|
||||
$obj->kalender_id = $rowstpl->kalender_id;
|
||||
|
||||
$stundenplan_data[] = $obj;
|
||||
}
|
||||
}
|
||||
return $stundenplan_data;
|
||||
}
|
||||
|
||||
public function addKalenderEvent($user, $ort_kurzbz, $start_date, $end_date, $lehreinheit_id)
|
||||
{
|
||||
$kalenderresult = $this->ci->KalenderModel->insert(array(
|
||||
'von' => $start_date,
|
||||
'bis' => $end_date,
|
||||
'typ' => 'lehreinheit',
|
||||
'status_kurzbz' => 'planning',
|
||||
'insertvon' => $user,
|
||||
'insertamum' => date('Y-m-d H:i:s')
|
||||
));
|
||||
|
||||
if(isSuccess($kalenderresult) && hasData($kalenderresult))
|
||||
{
|
||||
$kalender_id = getData($kalenderresult);
|
||||
|
||||
|
||||
$kalenderlehreinheitresult = $this->ci->KalenderLehreinheitModel->insert(array(
|
||||
'kalender_id' => $kalender_id,
|
||||
'lehreinheit_id' => $lehreinheit_id
|
||||
));
|
||||
|
||||
if(isSuccess($kalenderlehreinheitresult))
|
||||
{
|
||||
$kalenderOrtresult = $this->ci->KalenderOrtModel->insert(array(
|
||||
'kalender_id'=>$kalender_id,
|
||||
'ort_kurzbz'=>$ort_kurzbz
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function updateKalenderEvent($user, $kalender_id, $ort_kurzbz, $start_date, $end_date)
|
||||
{
|
||||
/*TODO Checks:
|
||||
Von-Tag muss gleich dem Bis-Tag sein
|
||||
Bis darf nicht vor von liegen
|
||||
|
||||
History erstellen
|
||||
Sync Status setzen
|
||||
*/
|
||||
$this->ci->KalenderModel->update($kalender_id,
|
||||
array(
|
||||
'von'=>$start_date,
|
||||
'updateamum'=>date('Y-m-d H:i:s'),
|
||||
'updatevon' => $user
|
||||
)
|
||||
);
|
||||
return success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
class Kalender_Lehreinheit_model extends DB_Model
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dbTable = 'lehre.tbl_kalender_lehreinheit';
|
||||
$this->pk = array('kalender_id','lehreinheit_id');
|
||||
$this->hasSequence = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
class Kalender_Ort_model extends DB_Model
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dbTable = 'lehre.tbl_kalender_ort';
|
||||
$this->pk = 'kalender_ort_id';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
class Kalender_model extends DB_Model
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dbTable = 'lehre.tbl_kalender';
|
||||
$this->pk = 'kalender_id';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
class Stundenplandev_Kalender_model extends DB_Model
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->dbTable = 'sync.tbl_stundenplandev_kalender';
|
||||
$this->pk = 'stundenplandev_kalender_id';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
$includesArray = array(
|
||||
'title' => 'Tempus',
|
||||
'axios027' => true,
|
||||
'bootstrap5' => true,
|
||||
'fontawesome6' => true,
|
||||
'vue3' => true,
|
||||
'vuedatepicker11' => true,
|
||||
'primevue3' => true,
|
||||
'tabulator5' => true,
|
||||
'phrases' => array(
|
||||
'global',
|
||||
'ui',
|
||||
'notiz',
|
||||
),
|
||||
'customCSSs' => [
|
||||
'public/css/components/vue-datepicker.css',
|
||||
'public/css/components/primevue.css',
|
||||
'public/css/components/calendar.css',
|
||||
'public/css/Tempus.css'
|
||||
],
|
||||
'customJSs' => [
|
||||
#'vendor/npm-asset/primevue/tree/tree.min.js',
|
||||
#'vendor/npm-asset/primevue/toast/toast.min.js'
|
||||
'vendor/moment/luxonjs/luxon.min.js'
|
||||
],
|
||||
'customJSModules' => [
|
||||
'public/js/apps/Tempus.js'
|
||||
]
|
||||
);
|
||||
|
||||
$this->load->view('templates/FHC-Header', $includesArray);
|
||||
?>
|
||||
<div id="main">
|
||||
<router-view
|
||||
default-semester="<?= $variables['semester_aktuell']; ?>"
|
||||
active-addons="<?= defined('ACTIVE_ADDONS') ? ACTIVE_ADDONS : ''; ?>"
|
||||
tempus-root="<?= site_url('Tempus'); ?>"
|
||||
cis-root="<?= CIS_ROOT; ?>"
|
||||
:permissions="<?= htmlspecialchars(json_encode($permissions)); ?>"
|
||||
:config="<?= htmlspecialchars(json_encode($variables)); ?>"
|
||||
>
|
||||
</router-view>
|
||||
</div>
|
||||
|
||||
<?php $this->load->view('templates/FHC-Footer', $includesArray); ?>
|
||||
@@ -0,0 +1,130 @@
|
||||
@import './Fhc.css';
|
||||
@import './components/searchbar/searchbar.css';
|
||||
@import './components/verticalsplit.css';
|
||||
@import './components/FilterComponent.css';
|
||||
@import './components/Tabs.css';
|
||||
@import './components/Notiz.css';
|
||||
|
||||
html {
|
||||
font-size: .875em;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
/*display: flex;*/
|
||||
height: 100%;
|
||||
}
|
||||
.heightfull {
|
||||
height: 95%;
|
||||
}
|
||||
.navbar-dark .navbar-brand:focus {
|
||||
box-shadow: 0 0 0 .25rem rgba(13,110,253,.25);
|
||||
z-index: 3;
|
||||
}
|
||||
#main {
|
||||
height: 100%;
|
||||
}
|
||||
.tempus {
|
||||
height: 100%;
|
||||
}
|
||||
.searchbar {
|
||||
margin-right: 0!important;
|
||||
}
|
||||
.searchbar > .input-group {
|
||||
margin-right: 0!important;
|
||||
}
|
||||
.searchbar > .input-group > * {
|
||||
border-radius: 0!important;
|
||||
}
|
||||
|
||||
#sidebarMenu {
|
||||
width: 0%;
|
||||
}
|
||||
|
||||
.tabulator-row.disabled.tabulator-row-odd .tabulator-cell {
|
||||
color: var(--gray-400);
|
||||
}
|
||||
.tabulator-row.disabled.tabulator-row-even .tabulator-cell {
|
||||
color: var(--gray-500);
|
||||
}
|
||||
|
||||
/* Dropdown Toolbar Interessent, submenu */
|
||||
.dropend .dropdown-toggle.d-flex::after {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
#sidebarMenu {
|
||||
visibility: visible!important;
|
||||
transform: none;
|
||||
position: inherit;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.toast.toast-success {
|
||||
color: #0f5132;
|
||||
background-color: #d1e7dd!important;
|
||||
border-color: #badbcc!important;
|
||||
}
|
||||
.toast.toast-danger {
|
||||
color: #842029;
|
||||
background-color: #f8d7da!important;
|
||||
border-color: #f5c2c7!important;
|
||||
}
|
||||
|
||||
.has-filter .fa-filter {
|
||||
color: var(--bs-success);
|
||||
}
|
||||
|
||||
#parkinglot {
|
||||
border: 1px dashed;
|
||||
width: 300px;
|
||||
height: 100px;
|
||||
color: #AAAAAA;
|
||||
text-align: center;
|
||||
font-size: large;
|
||||
margin-top: 20px;
|
||||
|
||||
}
|
||||
|
||||
#coursechooser {
|
||||
width: 300px;
|
||||
min-height: 100px;
|
||||
font-size: large;
|
||||
margin-top: 50px;
|
||||
border: 1px solid #ccc;
|
||||
background: #eee;
|
||||
text-align: left;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
#coursechooserheader {
|
||||
font-weight: bold;
|
||||
font-size: medium;
|
||||
}
|
||||
|
||||
#coursechooserfooter {
|
||||
font-size: small;
|
||||
color: #AAAAAA;
|
||||
}
|
||||
|
||||
.eckerl {
|
||||
width: 200px;
|
||||
margin: 10px 0;
|
||||
padding: 2px 4px;
|
||||
background: #00649c;
|
||||
color: #fff;
|
||||
font-size: .85em;
|
||||
cursor: pointer;
|
||||
border-radius: 2px;
|
||||
box-shadow: 3px 3px 3px #bbb;
|
||||
}
|
||||
|
||||
:root{
|
||||
--fhc-calendar-pane-height: calc(100vh - 120px);
|
||||
}
|
||||
|
||||
.eckerltest {
|
||||
box-shadow: 3px 3px 3px #ccc;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
export default {
|
||||
getCourses(searchfilter) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/tempus/getCourses',
|
||||
params: { searchfilter }
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
|
||||
export default {
|
||||
getRoomplan(ort_kurzbz, start_date, end_date) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Kalender/getRoomplan',
|
||||
params: { ort_kurzbz, start_date, end_date }
|
||||
};
|
||||
},
|
||||
getStundenplan(start_date, end_date) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Kalender/getStundenplan',
|
||||
params: { start_date, end_date}
|
||||
};
|
||||
},
|
||||
getStunden() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Kalender/Stunden',
|
||||
params: {}
|
||||
};
|
||||
},
|
||||
getOrtReservierungen(ort_kurzbz, start_date, end_date) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/Kalender/Reservierungen/${ort_kurzbz}`,
|
||||
params: { start_date, end_date}
|
||||
};
|
||||
},
|
||||
getStundenplanReservierungen(start_date, end_date) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Kalender/Reservierungen',
|
||||
params: { start_date, end_date }
|
||||
};
|
||||
},
|
||||
getLehreinheitStudiensemester(lehreinheit_id) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: `/api/frontend/v1/Kalender/getLehreinheitStudiensemester/${lehreinheit_id}`,
|
||||
params: {}
|
||||
};
|
||||
},
|
||||
updateKalenderEvent(kalender_id, ort_kurzbz, start_date, end_date) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Kalender/updateKalenderEvent',
|
||||
params: { kalender_id, ort_kurzbz, start_date, end_date}
|
||||
};
|
||||
},
|
||||
addKalenderEvent(lehreinheit_id, ort_kurzbz, start_date, end_date) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Kalender/addKalenderEvent',
|
||||
params: { lehreinheit_id, ort_kurzbz, start_date, end_date}
|
||||
};
|
||||
},
|
||||
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (C) 2024 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import FhcTempus from "../components/Tempus/Tempus.js";
|
||||
import fhcapifactory from "./api/fhcapifactory.js";
|
||||
|
||||
import Phrasen from "../plugins/Phrasen.js";
|
||||
|
||||
|
||||
const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
|
||||
|
||||
const router = VueRouter.createRouter({
|
||||
history: VueRouter.createWebHistory(),
|
||||
routes: [
|
||||
{ path: `/${ciPath}/Tempus`, component: FhcTempus },
|
||||
]
|
||||
});
|
||||
|
||||
const app = Vue.createApp();
|
||||
|
||||
app
|
||||
.use(router)
|
||||
.use(primevue.config.default, {
|
||||
zIndex: {
|
||||
overlay: 1100
|
||||
}
|
||||
})
|
||||
.use(Phrasen)
|
||||
.mount('#main');
|
||||
@@ -0,0 +1,168 @@
|
||||
import FhcCalendar from "./Base.js";
|
||||
|
||||
import ApiLvPlan from '../../api/factory/lvPlan.js';
|
||||
|
||||
import { useEventLoader } from '../../composables/EventLoader.js';
|
||||
|
||||
import ModeDay from './Mode/Day.js';
|
||||
import ModeWeek from './Mode/Week.js';
|
||||
import ModeMonth from './Mode/Month.js';
|
||||
|
||||
export default {
|
||||
name: "CalendarTempus",
|
||||
components: {
|
||||
FhcCalendar
|
||||
},
|
||||
inject: [
|
||||
"renderers"
|
||||
],
|
||||
props: {
|
||||
timezone: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
date: {
|
||||
type: [Date, String, Number, luxon.DateTime],
|
||||
default: luxon.DateTime.local()
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'Week'
|
||||
},
|
||||
getPromiseFunc: {
|
||||
type: Function,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: [
|
||||
"update:date",
|
||||
"update:mode",
|
||||
"update:range",
|
||||
"drop"
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
modes: {
|
||||
week: Vue.markRaw(ModeWeek),
|
||||
month: Vue.markRaw(ModeMonth)
|
||||
},
|
||||
modeOptions: {
|
||||
day: {
|
||||
emptyMessage: Vue.computed(() => this.$p.t('lehre/noLvFound')),
|
||||
emptyMessageDetails: Vue.computed(() => this.$p.t('lehre/noLvFound'))
|
||||
},
|
||||
week: {
|
||||
collapseEmptyDays: false
|
||||
}
|
||||
},
|
||||
teachingunits: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
backgrounds() {
|
||||
let now = luxon.DateTime.now().setZone(this.timezone);
|
||||
|
||||
if (this.mode == 'Month')
|
||||
return [
|
||||
{
|
||||
class: 'background-past',
|
||||
end: now.startOf('day')
|
||||
}
|
||||
];
|
||||
|
||||
return [
|
||||
{
|
||||
class: 'background-past',
|
||||
end: now,
|
||||
label: now.startOf('minute').toISOTime({ suppressSeconds: true, includeOffset: false })
|
||||
}
|
||||
];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
eventStyle(event) {
|
||||
if (!event.farbe)
|
||||
return undefined;
|
||||
return '--event-bg:#' + event.farbe;
|
||||
},
|
||||
updateRange(rangeInterval) {
|
||||
this.rangeInterval = rangeInterval;
|
||||
this.$emit('update:range', rangeInterval);
|
||||
},
|
||||
ondrop(e, start, end){
|
||||
this.$emit('drop', e, start, end);
|
||||
}
|
||||
},
|
||||
setup(props, context) {
|
||||
const rangeInterval = Vue.ref(null);
|
||||
|
||||
const { events, lv } = useEventLoader(rangeInterval, props.getPromiseFunc);
|
||||
|
||||
Vue.watch(lv, newValue => {
|
||||
context.emit('update:lv', newValue);
|
||||
});
|
||||
|
||||
return {
|
||||
rangeInterval,
|
||||
events,
|
||||
lv
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$api
|
||||
.call(ApiLvPlan.getStunden())
|
||||
.then(res => {
|
||||
return this.teachingunits = res.data.map(el => ({
|
||||
id: el.stunde,
|
||||
start: el.beginn,
|
||||
end: el.ende
|
||||
}));
|
||||
});
|
||||
},
|
||||
template: /* html */`
|
||||
<fhc-calendar
|
||||
ref="calendar"
|
||||
class="fhc-calendar-lvplan"
|
||||
:date="date"
|
||||
:modes="modes"
|
||||
:mode-options="modeOptions"
|
||||
:mode="mode"
|
||||
:timezone="timezone"
|
||||
:locale="$p.user_locale.value"
|
||||
:events="events || []"
|
||||
:backgrounds="backgrounds"
|
||||
:time-grid="teachingunits"
|
||||
show-btns
|
||||
@drop="ondrop"
|
||||
@update:date="(newDate, newMode) => $emit('update:date', newDate, newMode)"
|
||||
@update:mode="(newMode, newDate) => $emit('update:mode', newMode, newDate)"
|
||||
@update:range="updateRange"
|
||||
>
|
||||
<template v-slot="{ event, mode }">
|
||||
<div
|
||||
:class="'event-type-' + event.type + ' ' + mode + 'PageContainer'"
|
||||
:type="mode == 'day' ? 'button' : undefined"
|
||||
:style="eventStyle(event)"
|
||||
>
|
||||
<component
|
||||
v-if="mode == 'event'"
|
||||
:is="renderers[event.type]?.modalContent"
|
||||
:event="event"
|
||||
></component>
|
||||
<component
|
||||
v-else-if="mode == 'eventheader'"
|
||||
:is="renderers[event.type]?.modalTitle"
|
||||
:event="event"
|
||||
></component>
|
||||
<component
|
||||
v-else
|
||||
:is="renderers[event.type]?.calendarEvent"
|
||||
:event="event"
|
||||
></component>
|
||||
</div>
|
||||
</template>
|
||||
<template #actions>
|
||||
<slot />
|
||||
</template>
|
||||
</fhc-calendar>`
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import ApiCoursePicker from '../../api/factory/coursepicker.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
courses: null
|
||||
}
|
||||
},
|
||||
props: {
|
||||
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
methods: {
|
||||
loadCourses: function(){
|
||||
|
||||
Promise.allSettled([
|
||||
this.$api.call(ApiCoursePicker.getCourses("test")),
|
||||
]).then((result) => {
|
||||
let promise_events = [];
|
||||
result.forEach((promise_result) => {
|
||||
if (promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success") {
|
||||
let data = promise_result.value.data;
|
||||
if (data && data.forEach) {
|
||||
|
||||
data.forEach((entry, i) => {
|
||||
entry.showname = entry.studiengang_kurzbz+entry.semester+' - ' + entry.kurzbz + ' ' + entry.lektoren.toString();
|
||||
entry.tag = '';
|
||||
entry.mode = 'single';
|
||||
});
|
||||
}
|
||||
promise_events = promise_events.concat(data);
|
||||
}
|
||||
})
|
||||
this.courses = promise_events;
|
||||
|
||||
});
|
||||
},
|
||||
dragstart: function(evt, course) {
|
||||
const transferdata = {
|
||||
type: 'lehreinheit',
|
||||
id: course.lehreinheit_id,
|
||||
mode: course.mode
|
||||
};
|
||||
|
||||
event.dataTransfer.setData('text', JSON.stringify(transferdata));
|
||||
},
|
||||
keydown: function(evt, course) {
|
||||
|
||||
switch(evt.key)
|
||||
{
|
||||
case "1":
|
||||
course.tag = '#Singleweek';
|
||||
course.mode = 'single';
|
||||
break
|
||||
case "2":
|
||||
course.tag = '#Multiweek';
|
||||
course.mode = 'multi';
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
created() {
|
||||
this.loadCourses();
|
||||
//document.addEventListener('keydown', function () { console.log("a"); });
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
template: /*html*/`
|
||||
<div ref="container" class="fhc-coursechooser">
|
||||
<div id="coursechooser">
|
||||
<span id="coursechooserheader">Course</span>
|
||||
<input type="text" placeholder="Search"/>
|
||||
<div v-for="course in courses" class="eckerl" draggable="true" @dragstart="dragstart(event, course)" tabindex="0" @keyup="keydown($event, course)">
|
||||
{{course.showname}}
|
||||
{{course.tag}}
|
||||
</div>
|
||||
<span id="coursechooserfooter">Drag & Drop on Calender</span>
|
||||
</div>
|
||||
</div>`
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
/**
|
||||
* Copyright (C) 2024 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import VueDatePicker from '../vueDatepicker.js.php'
|
||||
import CoreSearchbar from "../searchbar/searchbar.js";
|
||||
import VerticalSplit from "../verticalsplit/verticalsplit.js";
|
||||
import FhcCalendar from "../Calendar/Tempus.js";
|
||||
import FhcCoursepicker from "../Tempus/Coursepicker.js";
|
||||
import ApiKalender from '../../api/factory/kalender.js';
|
||||
import ApiSearchbar from "../../api/factory/searchbar.js";
|
||||
import ApiRenderers from '../../api/factory/renderers.js';
|
||||
|
||||
export default {
|
||||
name: "Tempus",
|
||||
components: {
|
||||
CoreSearchbar,
|
||||
VerticalSplit,
|
||||
FhcCalendar,
|
||||
FhcCoursepicker
|
||||
},
|
||||
props: {
|
||||
defaultSemester: String,
|
||||
config: Object,
|
||||
permissions: Object,
|
||||
tempusRoot: String,
|
||||
cisRoot: String,
|
||||
activeAddons: String, // semicolon separated list of active addons
|
||||
viewData: Object,
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
cisRoot: this.cisRoot,
|
||||
defaultSemester: this.defaultSemester,
|
||||
$reloadList: () => {
|
||||
this.$refs.stvList.reload();
|
||||
},
|
||||
renderers: Vue.computed(() => this.renderers),
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selected: [],
|
||||
searchbaroptions: {
|
||||
origin: 'tempus',
|
||||
cssclass: "position-relative",
|
||||
calcheightonly: true,
|
||||
types: [
|
||||
//"student",
|
||||
"raum",
|
||||
//"mitarbeiter"
|
||||
],
|
||||
actions: {
|
||||
raum: {
|
||||
defaultaction: {
|
||||
type: "function",
|
||||
action: this.setOrt
|
||||
},
|
||||
childactions: [
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
lv_id: null,
|
||||
events: null,
|
||||
minimized: false,
|
||||
calendarDate: luxon.DateTime.local(), //new CalendarDate(new Date()),
|
||||
currentlySelectedEvent: null,
|
||||
//currentDay: new Date(),
|
||||
studiensemesterKurzbz: this.defaultSemester,
|
||||
lists: {
|
||||
nations: [],
|
||||
sprachen: [],
|
||||
geschlechter: []
|
||||
},
|
||||
renderers: null,
|
||||
ort_kurzbz: 'EDV_A5.08',
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setOrt: function(data)
|
||||
{
|
||||
// Wenn bei der Suche ein Ort ausgewaehlt wird, dann wir der Ort gesetzt und ein Reload getriggert durch den watcher
|
||||
this.ort_kurzbz = data.ort_kurzbz;
|
||||
},
|
||||
handleChangeDate() {
|
||||
},
|
||||
handleChangeMode() {
|
||||
},
|
||||
searchfunction(params) {
|
||||
return this.$api.call(ApiSearchbar.search(params));
|
||||
},
|
||||
getPromiseFunc(start, end) {
|
||||
return [
|
||||
this.$api.call(ApiKalender.getRoomplan(this.ort_kurzbz, '2025-10-01','2025-10-30')),//start.toISODate(), end.toISODate())),
|
||||
];
|
||||
},
|
||||
parkingdrop: function(evt)
|
||||
{
|
||||
evt.preventDefault();
|
||||
var data = JSON.parse(evt.dataTransfer.getData("text"));
|
||||
alert('parked Data:'+data.id);
|
||||
console.log(data);
|
||||
},
|
||||
dropHandler: function(event, start, end)
|
||||
{
|
||||
let day = start.date.toFormat('yyyy-MM-dd');
|
||||
let time = start.date.toFormat('hh:mm');
|
||||
|
||||
let dropdata = JSON.parse(event.dataTransfer.getData('text'))
|
||||
|
||||
if(dropdata.type=='kalender')
|
||||
{
|
||||
let kalender_id = dropdata.id;
|
||||
|
||||
Promise.allSettled([
|
||||
this.$api.call(ApiKalender.updateKalenderEvent(kalender_id, this.ort_kurzbz, day+' '+time, null))
|
||||
]).then((result) => {
|
||||
let promise_events = [];
|
||||
result.forEach((promise_result) => {
|
||||
if (promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success")
|
||||
{
|
||||
// TODO - reload
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
else if(dropdata.type=='lehreinheit')
|
||||
{
|
||||
// TODO Calculate end time
|
||||
let lehreinheit_id = dropdata.id;
|
||||
let start_time = day+' '+time;
|
||||
let end_time = start.date.plus({ minutes: 45 }).toFormat('yyyy-MM-dd hh:mm');
|
||||
alert("mode:"+dropdata.mode);
|
||||
|
||||
Promise.allSettled([
|
||||
this.$api.call(ApiKalender.addKalenderEvent(lehreinheit_id, this.ort_kurzbz, start_time, end_time))
|
||||
]).then((result) => {
|
||||
let promise_events = [];
|
||||
result.forEach((promise_result) => {
|
||||
if (promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success") {
|
||||
|
||||
// TODO - reload
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
alert("Unbekannte Daten gedroppt");
|
||||
}
|
||||
},
|
||||
onRightClick: function(evt) {
|
||||
this.$refs.EventContextMenu.show(evt);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
ort_kurzbz: function (newValue, oldValue) {
|
||||
// Raumansicht laden wenn der Ort geaendert wird
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentDay() {
|
||||
return luxon.DateTime.now().setZone(this.config.timezone).toISODate();
|
||||
},
|
||||
currentMode() {
|
||||
return 'week';
|
||||
},
|
||||
},
|
||||
async created()
|
||||
{
|
||||
await this.$api
|
||||
.call(ApiRenderers.loadRenderers())
|
||||
.then(res => res.data)
|
||||
.then(data => {
|
||||
for (let rendertype of Object.keys(data)) {
|
||||
let modalTitle = null;
|
||||
let modalContent = null;
|
||||
let calendarEvent = null;
|
||||
if (data[rendertype].modalTitle)
|
||||
modalTitle = Vue.markRaw(Vue.defineAsyncComponent(() => import(data[rendertype].modalTitle)));
|
||||
if (data[rendertype].modalContent)
|
||||
modalContent = Vue.markRaw(Vue.defineAsyncComponent(() => import(data[rendertype].modalContent)));
|
||||
if (data[rendertype].calendarEvent)
|
||||
calendarEvent = Vue.markRaw(Vue.defineAsyncComponent(() => import(data[rendertype].calendarEvent)));
|
||||
|
||||
if (data[rendertype].calendarEventStyles){
|
||||
var head = document.head;
|
||||
if(!head.querySelector(`link[href="${data[rendertype].calendarEventStyles}"]`)){
|
||||
var link = document.createElement("link");
|
||||
link.type = "text/css";
|
||||
link.rel = "stylesheet";
|
||||
link.href = data[rendertype].calendarEventStyles;
|
||||
head.appendChild(link);
|
||||
}
|
||||
}
|
||||
|
||||
if(this.renderers === null) {
|
||||
this.renderers = {};
|
||||
}
|
||||
if (!this.renderers[rendertype]) {
|
||||
this.renderers[rendertype] = {}
|
||||
}
|
||||
this.renderers[rendertype].modalTitle = modalTitle;
|
||||
this.renderers[rendertype].modalContent = modalContent;
|
||||
this.renderers[rendertype].calendarEvent = calendarEvent;
|
||||
}
|
||||
});
|
||||
},
|
||||
mounted() {
|
||||
|
||||
|
||||
},
|
||||
template: `
|
||||
<div class="tempus">
|
||||
<header class="navbar navbar-expand-lg navbar-dark bg-dark flex-md-nowrap p-0 shadow">
|
||||
<a class="navbar-brand col-md-4 col-lg-3 col-xl-2 me-0 px-3">Tempus</a>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Config</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Issues</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
Reports
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" href="#">AZG Verletzungen</a></li>
|
||||
<li><a class="dropdown-item" href="#">Raumauslastung</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="#">LektorInnenliste</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<core-searchbar :searchoptions="searchbaroptions" :searchfunction=searchfunction class="searchbar w-100"></core-searchbar>
|
||||
</header>
|
||||
<div class="container-fluid overflow-hidden heightfull">
|
||||
<div class="row h-100">
|
||||
<nav id="sidebarMenu" class="bg-light offcanvas offcanvas-start col-md p-md-0 h-100">
|
||||
<div class="offcanvas-header justify-content-end px-1 d-md-none">
|
||||
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" :aria-label="$p.t('ui/schliessen')"></button>
|
||||
</div>
|
||||
<div style="float: left">
|
||||
<fhc-coursepicker></fhc-coursepicker>
|
||||
<div id="parkinglot" ondragover="event.preventDefault();" @drop="parkingdrop">
|
||||
<br />
|
||||
<i class="fa-solid fa-square-parking"></i><br />
|
||||
<span>Drag here to park</span>
|
||||
</div>
|
||||
<br />
|
||||
Raum <input type="text" v-model="ort_kurzbz">
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<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"
|
||||
:date="currentDay"
|
||||
:mode="currentMode"
|
||||
@drop="dropHandler"
|
||||
@update:date="handleChangeDate"
|
||||
@update:mode="handleChangeMode"
|
||||
class="responsive-calendar"
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
};
|
||||
@@ -84,6 +84,7 @@ require_once('dbupdate_3.4/60882_lehrfaecherverteilung_favorites.php');
|
||||
require_once('dbupdate_3.4/66982_berufsschule.php');
|
||||
require_once('dbupdate_3.4/40314_electronic_onboarding_anbindung_ida.php');
|
||||
require_once('dbupdate_3.4/47972_pruefungsverwaltung_ects_angabe.php');
|
||||
require_once('dbupdate_3.4/46975_tempus.php');
|
||||
|
||||
// *** Pruefung und hinzufuegen der neuen Attribute und Tabellen
|
||||
echo '<H2>Pruefe Tabellen und Attribute!</H2>';
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
if (! defined('DB_NAME')) exit('No direct script access allowed');
|
||||
|
||||
// Kalender Tabelle fuer neues Tempus
|
||||
if(!$result = @$db->db_query("SELECT kalender_id FROM lehre.tbl_kalender LIMIT 1"))
|
||||
{
|
||||
$qry = "CREATE TABLE lehre.tbl_kalender (
|
||||
kalender_id bigserial NOT NULL,
|
||||
von timestamp NOT NULL,
|
||||
bis timestamp NOT NULL,
|
||||
typ character varying(32),
|
||||
status_kurzbz character varying(32),
|
||||
vorgaenger_kalender_id bigint,
|
||||
insertamum timestamp DEFAULT now(),
|
||||
insertvon character varying(32),
|
||||
updateamum timestamp DEFAULT now(),
|
||||
updatevon character varying(32),
|
||||
CONSTRAINT tbl_kalender_pk PRIMARY KEY (kalender_id)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE lehre.tbl_kalender IS 'Schedule Calendar Events';
|
||||
|
||||
CREATE TABLE lehre.tbl_kalender_typ (
|
||||
typ character varying(32) NOT NULL,
|
||||
CONSTRAINT tbl_kalender_typ_pk PRIMARY KEY (typ)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE lehre.tbl_kalender_typ IS 'Type of Calendar Events';
|
||||
|
||||
INSERT INTO lehre.tbl_kalender_typ (typ) VALUES (E'lehreinheit');
|
||||
INSERT INTO lehre.tbl_kalender_typ (typ) VALUES (E'reservierung');
|
||||
INSERT INTO lehre.tbl_kalender_typ (typ) VALUES (E'event');
|
||||
|
||||
CREATE TABLE lehre.tbl_kalender_lehreinheit (
|
||||
lehreinheit_id integer NOT NULL,
|
||||
kalender_id bigint NOT NULL,
|
||||
CONSTRAINT tbl_kalender_lehreinheit_pk PRIMARY KEY (lehreinheit_id,kalender_id)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE lehre.tbl_kalender_lehreinheit IS 'Connects Calender Events to Courses';
|
||||
|
||||
ALTER TABLE lehre.tbl_kalender_lehreinheit ADD CONSTRAINT tbl_lehreinheit_fk FOREIGN KEY (lehreinheit_id)
|
||||
REFERENCES lehre.tbl_lehreinheit (lehreinheit_id) MATCH FULL
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
CREATE TABLE lehre.tbl_kalender_ort (
|
||||
kalender_ort_id bigserial NOT NULL,
|
||||
location text,
|
||||
ort_kurzbz character varying(32),
|
||||
kalender_id bigint,
|
||||
CONSTRAINT tbl_kalender_ort_pk PRIMARY KEY (kalender_ort_id)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE lehre.tbl_kalender_ort IS E'Connects one Calendar Entry to multiple Rooms';
|
||||
|
||||
COMMENT ON COLUMN lehre.tbl_kalender_ort.location IS E'Text Description if not a physical inhouse Room (External Location, Conference Link, etc)';
|
||||
|
||||
ALTER TABLE lehre.tbl_kalender_ort ADD CONSTRAINT tbl_kalender_fk FOREIGN KEY (kalender_id)
|
||||
REFERENCES lehre.tbl_kalender (kalender_id) MATCH FULL
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE lehre.tbl_kalender_ort ADD CONSTRAINT tbl_ort_fk FOREIGN KEY (ort_kurzbz)
|
||||
REFERENCES public.tbl_ort (ort_kurzbz) MATCH FULL
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE lehre.tbl_kalender_lehreinheit ADD CONSTRAINT tbl_kalender_fk FOREIGN KEY (kalender_id)
|
||||
REFERENCES lehre.tbl_kalender (kalender_id) MATCH FULL
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
CREATE TABLE lehre.tbl_kalender_status (
|
||||
status_kurzbz character varying(32) NOT NULL,
|
||||
bezeichnung text,
|
||||
CONSTRAINT tbl_kalender_status_pk PRIMARY KEY (status_kurzbz)
|
||||
);
|
||||
|
||||
COMMENT ON TABLE lehre.tbl_kalender_status IS 'Calender visibility Status';
|
||||
|
||||
INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'planning', E'planning');
|
||||
INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'tosync', E'tosync');
|
||||
INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'todelete', E'todelete');
|
||||
INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'visible_lektor', E'Sichtbar für Lektoren');
|
||||
INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'deleted', E'deleted');
|
||||
INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'archived', E'archived');
|
||||
INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'visible_student', E'Sichtbar für Studierende');
|
||||
|
||||
ALTER TABLE lehre.tbl_kalender ADD CONSTRAINT tbl_kalender_status_fk FOREIGN KEY (status_kurzbz)
|
||||
REFERENCES lehre.tbl_kalender_status (status_kurzbz) MATCH FULL
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
ALTER TABLE lehre.tbl_kalender ADD CONSTRAINT tbl_kalender_typ_fk FOREIGN KEY (typ)
|
||||
REFERENCES lehre.tbl_kalender_typ (typ) MATCH FULL
|
||||
ON DELETE RESTRICT ON UPDATE CASCADE;
|
||||
|
||||
GRANT SELECT, UPDATE, INSERT, DELETE ON lehre.tbl_kalender to vilesci;
|
||||
GRANT SELECT, UPDATE, INSERT, DELETE ON lehre.tbl_kalender to web;
|
||||
|
||||
GRANT SELECT, UPDATE, INSERT, DELETE ON lehre.tbl_kalender_status to vilesci;
|
||||
GRANT SELECT ON lehre.tbl_kalender_status to web;
|
||||
|
||||
GRANT SELECT, UPDATE, INSERT, DELETE ON lehre.tbl_kalender_lehreinheit to vilesci;
|
||||
GRANT SELECT, UPDATE, INSERT, DELETE ON lehre.tbl_kalender_lehreinheit to web;
|
||||
|
||||
GRANT SELECT, UPDATE, INSERT, DELETE ON lehre.tbl_kalender_ort to vilesci;
|
||||
GRANT SELECT, UPDATE, INSERT, DELETE ON lehre.tbl_kalender_ort to web;
|
||||
|
||||
GRANT SELECT, UPDATE, INSERT, DELETE ON lehre.tbl_kalender_typ to vilesci;
|
||||
GRANT SELECT ON lehre.tbl_kalender_typ to web;
|
||||
|
||||
CREATE TABLE sync.tbl_stundenplandev_kalender(
|
||||
stundenplandev_kalender_id bigserial NOT NULL,
|
||||
stundenplandev_id integer NOT NULL,
|
||||
kalender_id bigint NOT NULL,
|
||||
lastupdate timestamp,
|
||||
CONSTRAINT tbl_stundenplandev_kalender_pk PRIMARY KEY (stundenplandev_kalender_id)
|
||||
);
|
||||
|
||||
GRANT SELECT, UPDATE, INSERT, DELETE ON sync.tbl_stundenplandev_kalender to vilesci;
|
||||
COMMENT ON TABLE sync.tbl_stundenplandev_kalender IS 'Migration from old Stundenplan to new Kalender Table';
|
||||
|
||||
GRANT USAGE ON lehre.tbl_kalender_kalender_id_seq TO vilesci;
|
||||
GRANT USAGE ON lehre.tbl_kalender_kalender_id_seq TO web;
|
||||
GRANT USAGE ON sync.tbl_stundenplandev_kalender_stundenplandev_kalender_id_seq TO vilesci;
|
||||
GRANT USAGE ON lehre.tbl_kalender_ort_kalender_ort_id_seq TO vilesci;
|
||||
|
||||
CREATE INDEX idx_kalender_ort_kalender_id ON lehre.tbl_kalender_ort USING btree (kalender_id);
|
||||
CREATE INDEX idx_kalender_ort_kalender_id_ort_kurzbz ON lehre.tbl_kalender_ort USING btree (ort_kurzbz, kalender_id);
|
||||
CREATE INDEX idx_kalender_von ON lehre.tbl_kalender USING btree (von);
|
||||
";
|
||||
|
||||
if(!$db->db_query($qry))
|
||||
echo '<strong>lehre.tbl_kalender: '.$db->db_last_error().'</strong><br>';
|
||||
else
|
||||
echo '<br>lehre.tbl_kalender: neue Tabellen hinzugefuegt';
|
||||
}
|
||||
Reference in New Issue
Block a user