From b76bdfa4314cb4d365590aa61f544e6b6c69a511 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Mon, 4 Aug 2025 14:08:59 +0200 Subject: [PATCH 1/7] Close calendar modal on unmount --- public/js/components/Calendar/Base.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/public/js/components/Calendar/Base.js b/public/js/components/Calendar/Base.js index 2069347da..36d9877da 100644 --- a/public/js/components/Calendar/Base.js +++ b/public/js/components/Calendar/Base.js @@ -258,6 +258,9 @@ export default { this.modalEvent.closeFn(); } }, + beforeUnmount() { + this.hideEventModal(); + }, template: /* html */`
Date: Mon, 4 Aug 2025 14:09:27 +0200 Subject: [PATCH 2/7] Refactor LvPlan endpoints to be more granular --- .../controllers/api/frontend/v1/LvPlan.php | 218 +++++---- application/libraries/StundenplanLib.php | 423 ++++++++++-------- public/js/api/factory/lvPlan.js | 17 +- 3 files changed, 397 insertions(+), 261 deletions(-) diff --git a/application/controllers/api/frontend/v1/LvPlan.php b/application/controllers/api/frontend/v1/LvPlan.php index 6a1f9bf7f..b6c629fe1 100644 --- a/application/controllers/api/frontend/v1/LvPlan.php +++ b/application/controllers/api/frontend/v1/LvPlan.php @@ -36,6 +36,8 @@ class LvPlan extends FHCAPI_Controller 'Stunden' => self::PERM_LOGGED, 'getReservierungen' => self::PERM_LOGGED, 'LvPlanEvents' => self::PERM_LOGGED, + 'eventsPersonal' => self::PERM_LOGGED, + 'eventsLv' => self::PERM_LOGGED, 'getLehreinheitStudiensemester' => self::PERM_LOGGED, 'studiensemesterDateInterval' => self::PERM_LOGGED, 'getLvPlanForStudiensemester' => self::PERM_LOGGED, @@ -51,100 +53,95 @@ class LvPlan extends FHCAPI_Controller )); $this->load->library('form_validation'); - - //load models - $this->load->model('ressource/Stundenplan_model', 'StundenplanModel'); - $this->load->model('ressource/Reservierung_model', 'ReservierungModel'); - - } //------------------------------------------------------------------------------------------------------------------ // Public methods - /** + /** * fetches LvPlan and Moodle events together * @access public * */ - public function LvPlanEvents(){ + public function LvPlanEvents() + { + $hasLv = $this->input->post('lv_id'); + + return $hasLv ? $this->eventsLv() : $this->eventsPersonal(); + } + + /** + * fetches LvPlan, Moodle and Ferien events together for the logged in user + * + * @access public + */ + public function eventsPersonal() + { $this->load->library('StundenplanLib'); // 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"); - if ($this->form_validation->run() === FALSE) + + if (!$this->form_validation->run()) $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); - $lv_id = $this->input->get('lv_id', TRUE); + // storing the post parameter in local variables + $start_date = $this->input->post('start_date', true); + $end_date = $this->input->post('end_date', true); - $res_lvplan_events = $this->stundenplanlib->getStundenplan($start_date,$end_date,$lv_id); - $lvplan_events = $this->getDataOrTerminateWithError($res_lvplan_events); - if( is_null($lvplan_events) || isEmptyArray($lvplan_events) ) - { - $lvplan_events = array(); - } + // fetching lvplan events + $result = $this->stundenplanlib->getEventsUser($start_date, $end_date); + $lvplanEvents = $this->getDataOrTerminateWithError($result); // fetching moodle events - $this->load->config('calendar'); - $tz = new DateTimeZone($this->config->item('timezone')); - $start = new DateTime($start_date); - $start->setTimezone($tz); - $end = new DateTime($end_date); - $end->setTimezone($tz); - $end->modify('+1 day -1 second'); - $moodle_events = []; - Events::trigger( - 'moodleCalendarEvents', - function & () use (&$moodle_events) { - return $moodle_events; - }, - [ - 'start_date' => $start->format('c'), - 'end_date' => $end->format('c'), - 'username' => getAuthUID() - ] - ); + $moodleEvents = $this->fetchMoodleEvents($start_date, $end_date); - $lvAndMoodleEvents = array_merge($lvplan_events,$moodle_events); + // fetching ferien events + $ferienEvents = $this->fetchFerienEvents($start_date, $end_date); + - $this->load->model('education/Studentlehrverband_model','StudentLehrverbandModel'); - $this->load->model('organisation/Studiensemester_model','StudiensemesterModel'); - $current_Studiensemester = $this->StudiensemesterModel->getByDate($start_date); - $current_Studiensemester = $this->getDataOrTerminateWithError($current_Studiensemester); - $current_Studiensemester = current($current_Studiensemester)->studiensemester_kurzbz; - $studiengang = $this->StudentLehrverbandModel->loadWhere(["student_uid"=>getAuthUID(),"studiensemester_kurzbz"=>$current_Studiensemester]); - $studiengang = $this->getDataOrTerminateWithError($studiengang); - if(!empty($studiengang)){ - $studiengang = current($studiengang)->studiengang_kz; - }else{ - $studiengang = 0; - } + $this->terminateWithSuccess(array_merge( + $lvplanEvents, + $moodleEvents, + $ferienEvents + )); + } - $ferienEvents = $this->stundenplanlib->fetchFerienTageEvents($start_date, $end_date, $studiengang); - $ferienEvents = $this->getDataOrTerminateWithError($ferienEvents); - $allEvents = array_merge($lvAndMoodleEvents,$ferienEvents); - // sort array with moodle events first - usort($lvAndMoodleEvents, function($a, $b){ - if ($a->type === 'moodle' && $b->type !== 'moodle') { - return -1; - } elseif ($a->type !== 'moodle' && $b->type === 'moodle') { - return 1; - } elseif ($a->type === 'ferien' && ($b->type !== 'moodle' && $b->type !== 'ferien')) { - return -1; - } elseif (($a->type !== 'ferien' && $a->type !== 'moodle') && $b->type === 'ferien') { - return 1; - } else { - return 0; - } - }); + /** + * fetches LvPlan and Ferien events together for the lv + * + * @access public + */ + public function eventsLv() + { + $this->load->library('StundenplanLib'); - $this->terminateWithSuccess($allEvents); + // form validation + $this->form_validation->set_rules('start_date', "start_date", "required"); + $this->form_validation->set_rules('end_date', "end_date", "required"); + $this->form_validation->set_rules('lv_id', "lv_id", "required|integer"); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // storing the post parameter in local variables + $start_date = $this->input->post('start_date', true); + $end_date = $this->input->post('end_date', true); + $lv_id = $this->input->post('lv_id', true); + + // fetching lvplan events + $result = $this->stundenplanlib->getEventsLv($lv_id, $start_date, $end_date); + $lvplanEvents = $this->getDataOrTerminateWithError($result); + + // fetching ferien events + $ferienEvents = $this->fetchFerienEvents($start_date, $end_date); + + + $this->terminateWithSuccess(array_merge( + $lvplanEvents, + $ferienEvents + )); } //TODO: delete this function if we don't use the old calendar export endpoints anymore @@ -193,9 +190,6 @@ class LvPlan extends FHCAPI_Controller */ public function getRoomplan() { - // form validation - $this->load->library('form_validation'); - $this->form_validation->set_rules('ort_kurzbz', "Ort", "required"); $this->form_validation->set_rules('start_date', "start_date", "required"); $this->form_validation->set_rules('end_date', "end_date", "required"); @@ -228,9 +222,6 @@ class LvPlan extends FHCAPI_Controller */ public function getReservierungen($ort_kurzbz = null) { - //form validation - $this->load->library('form_validation'); - $this->form_validation->set_rules('start_date', "StartDate", "required"); $this->form_validation->set_rules('end_date', "EndDate", "required"); @@ -259,6 +250,77 @@ class LvPlan extends FHCAPI_Controller $this->terminateWithSuccess($result); } - + /** + * fetch moodle events + * + * @param string $start_date + * @param string $end_date + * @return array + */ + private function fetchMoodleEvents($start_date, $end_date) + { + $this->load->config('calendar'); + $tz = new DateTimeZone($this->config->item('timezone')); + + $start = new DateTime($start_date); + $start->setTimezone($tz); + + $end = new DateTime($end_date); + $end->setTimezone($tz); + $end->modify('+1 day -1 second'); + + $moodle_events = []; + + Events::trigger( + 'moodleCalendarEvents', + function & () use (&$moodle_events) { + return $moodle_events; + }, + [ + 'start_date' => $start->format('c'), + 'end_date' => $end->format('c'), + 'username' => getAuthUID() + ] + ); + + return $moodle_events; + } + + /** + * fetch ferien events + * + * @param string $start_date + * @param string $end_date + * @return array + */ + private function fetchFerienEvents($start_date, $end_date) + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->load->model('education/Studentlehrverband_model', 'StudentLehrverbandModel'); + + $currentStudiensemester = $this->StudiensemesterModel->getByDate($start_date); + $currentStudiensemester = $this->getDataOrTerminateWithError($currentStudiensemester); + + if ($currentStudiensemester) { + $studentsemester_kurzbz = current($currentStudiensemester)->studiensemester_kurzbz; + + $studiengang = $this->StudentLehrverbandModel->loadWhere([ + "student_uid" => getAuthUID(), + "studiensemester_kurzbz" => $studentsemester_kurzbz + ]); + $studiengang = $this->getDataOrTerminateWithError($studiengang); + + if ($studiengang) + $studiengang_kz = current($studiengang)->studiengang_kz; + else + $studiengang_kz = 0; + } else { + $studiengang_kz = 0; + } + + $ferienEvents = $this->stundenplanlib->fetchFerienTageEvents($start_date, $end_date, $studiengang_kz); + + return $this->getDataOrTerminateWithError($ferienEvents); + } } diff --git a/application/libraries/StundenplanLib.php b/application/libraries/StundenplanLib.php index 488fff45a..6d53a2e2e 100644 --- a/application/libraries/StundenplanLib.php +++ b/application/libraries/StundenplanLib.php @@ -8,125 +8,177 @@ use \DateTimeZone as DateTimeZone; use \DateInterval as DateInterval; use \DatePeriod as DatePeriod; -class StundenplanLib{ +class StundenplanLib +{ private $_ci; // Code igniter instance /** - * fetches Stundenplan events from a UID and start/end date - * @access public + * fetches Stundenplan events for the loggedin user between start and end + * or for a lv * + * @param string $start + * @param string $end + * @param string|null $lehrveranstaltung_id + * @return stdClass + * @access public */ - public function getStundenplan($start_date, $end_date, $lv_id = null){ + public function getStundenplan($start, $end, $lehrveranstaltung_id = null) + { + if (!$lehrveranstaltung_id && $lehrveranstaltung_id !== 0) + return $this->getEventsUser($start, $end); + + return $this->getEventsLv($lehrveranstaltung_id, $start, $end); + } + + /** + * fetches Stundenplan events for the loggedin user between start and end + * + * @param string $start + * @param string $end + * @return stdClass + * @access public + */ + public function getEventsUser($start, $end) + { $this->_ci =& get_instance(); - // Load Config - $this->_ci->load->config('calendar'); + $this->_ci->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); - $this->_ci->load->model('ressource/Mitarbeiter_model','MitarbeiterModel'); - $this->_ci->load->model('organisation/Studiensemester_model','StudiensemesterModel'); - $this->_ci->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel'); - $this->_ci->load->model('person/Benutzergruppe_model','BenutzergruppeModel'); - $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); - - - $student_uid = getAuthUID(); - if(is_null($student_uid)) - { + $uid = getAuthUID(); + if (is_null($uid)) return error("No UID"); - } - $semester_range = $this->studienSemesterErmitteln($start_date,$end_date); - if(isError($semester_range)) - { - return error(getData($semester_range)); - } + $is_mitarbeiter = getData($this->_ci->MitarbeiterModel->isMitarbeiter($uid)); + + if ($is_mitarbeiter) + return $this->getEventsEmployee($uid, $start, $end); + + return $this->getEventsStudent($uid, $start, $end); + } + + /** + * fetches Stundenplan events for a student between start and end + * + * @param string $student_uid + * @param string $start + * @param string $end + * @return stdClass + * @access public + */ + public function getEventsStudent($student_uid, $start, $end) + { + $this->_ci =& get_instance(); + + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + + $semester_range = $this->studienSemesterErmitteln($start, $end); + if (isError($semester_range)) + return $semester_range; $semester_range = getData($semester_range); + $this->sortStudienSemester($semester_range); + $function_error = $this->applyLoadUeberSemesterHaelfte($semester_range); - if(!is_null($function_error)){ + if ($function_error) return $function_error; - } - if($lv_id) { // fetch Stundenplan for lva, irrelevant of who is requesting it (for now) + // getting the gruppen_kurzbz of the student in the different studiensemester + $benutzer_gruppen = $this->fetchBenutzerGruppenFromStudiensemester($student_uid, $semester_range); + if (isError($benutzer_gruppen)) + return $benutzer_gruppen; + $benutzer_gruppen = getData($benutzer_gruppen); - $stundenplan_data = $this->_ci->StundenplanModel->getStundenplanLVA($start_date, $end_date, $lv_id); - if(isError($stundenplan_data)) - { - return error(getData($stundenplan_data)); - } - $stundenplan_data = getData($stundenplan_data) ?? []; - $function_error = $this->expand_object_information($stundenplan_data); - if(!is_null($function_error)){ - return $function_error; - } - - // query lv itself in case its Stundenplan is being queried and it has no entries - $this->_ci->load->model('education/Lehrveranstaltung_model','LehrveranstaltungModel'); - $lv_result = $this->_ci->LehrveranstaltungModel->load($lv_id); - if(isError($lv_result)) - { - return error(getData($lv_result)); - } - $lv = getData($lv_result)[0]; - return success($stundenplan_data); - } + // getting the student_lehrverbaende of the student in the different studiensemester + $student_lehrverband = $this->fetchStudentlehrverbandFromStudiensemester($student_uid, $semester_range); + if (isError($student_lehrverband)) + return $student_lehrverband; + $student_lehrverband = getData($student_lehrverband); - $is_mitarbeiter = getData($this->_ci->MitarbeiterModel->isMitarbeiter($student_uid)); - if($is_mitarbeiter) - { - - $stundenplan_data = $this->_ci->StundenplanModel->getStundenplanMitarbeiter($start_date, $end_date, $student_uid); - if(isError($stundenplan_data)) - { - return error(getData($stundenplan_data)); - } - $stundenplan_data = getData($stundenplan_data) ?? []; - $function_error = $this->expand_object_information($stundenplan_data); - if(!is_null($function_error)){ - return error($function_error); - } - return success($stundenplan_data); - } else { - // getting the gruppen_kurzbz of the student in the different studiensemester - $benutzer_gruppen = $this->fetchBenutzerGruppenFromStudiensemester($semester_range); - if(isError($benutzer_gruppen)) - { - return error(getData($benutzer_gruppen)); - } - $benutzer_gruppen = getData($benutzer_gruppen); - - // getting the student_lehrverbaende of the student in the different studiensemester - $student_lehrverband = $this->fetchStudentlehrverbandFromStudiensemester($semester_range); - if(isError($student_lehrverband)) - { - return error(getData($student_lehrverband)); - } - $student_lehrverband = getData($student_lehrverband); - - $stundenplan_query = $this->_ci->StundenplanModel->getStundenplanQuery($start_date, $end_date, $semester_range, $benutzer_gruppen, $student_lehrverband); - if(!$stundenplan_query) - { - return success([]); - } - - - $stundenplan_data = $this->_ci->StundenplanModel->stundenplanGruppierung($stundenplan_query); - if(isError($stundenplan_data)) - { - return error(getData($stundenplan_data)); - } - $stundenplan_data = getData($stundenplan_data) ?? []; - - $function_error = $this->expand_object_information($stundenplan_data); - if(!is_null($function_error)){ - return $function_error; - } - - return success($stundenplan_data); - } + $stundenplan_query = $this->_ci->StundenplanModel->getStundenplanQuery( + $start, + $end, + $semester_range, + $benutzer_gruppen, + $student_lehrverband + ); + if (!$stundenplan_query) + return success([]); + $stundenplan_data = $this->_ci->StundenplanModel->stundenplanGruppierung($stundenplan_query); + if (isError($stundenplan_data)) + return $stundenplan_data; + $stundenplan_data = getData($stundenplan_data) ?? []; + + $function_error = $this->expandObjectInformation($stundenplan_data); + if ($function_error) + return $function_error; + + return success($stundenplan_data); + } + + /** + * fetches Stundenplan events for an employee between start and end + * + * @param string $uid + * @param string $start + * @param string $end + * @return stdClass + * @access public + */ + public function getEventsEmployee($uid, $start, $end) + { + $this->_ci =& get_instance(); + + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + + $stundenplan_data = $this->_ci->StundenplanModel->getStundenplanMitarbeiter($start, $end, $uid); + if (isError($stundenplan_data)) + return $stundenplan_data; + $stundenplan_data = getData($stundenplan_data) ?? []; + + $function_error = $this->expandObjectInformation($stundenplan_data); + if ($function_error) + return $function_error; + + return success($stundenplan_data); + } + + /** + * fetches Stundenplan events for a LV between start and end + * + * @param integer $lehrveranstaltung_id + * @param string $start + * @param string $end + * @return stdClass + * @access public + */ + public function getEventsLv($lehrveranstaltung_id, $start, $end) + { + $this->_ci =& get_instance(); + + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + + $stundenplan_data = $this->_ci->StundenplanModel->getStundenplanLVA($start, $end, $lehrveranstaltung_id); + if (isError($stundenplan_data)) + return $stundenplan_data; + $stundenplan_data = getData($stundenplan_data) ?? []; + + $function_error = $this->expandObjectInformation($stundenplan_data); + if ($function_error) + return $function_error; + + // query lv itself in case its Stundenplan is being queried and it has no entries + $this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $lv_result = $this->_ci->LehrveranstaltungModel->load($lehrveranstaltung_id); + if (isError($lv_result)) + return $lv_result; + if (!hasData($lv_result)) + return error('LV not found'); + + return success($stundenplan_data); } /** @@ -152,7 +204,7 @@ class StundenplanLib{ if (isError($roomplan_data)) return $roomplan_data; - $this->expand_object_information($roomplan_data->retval); + $this->expandObjectInformation($roomplan_data->retval); return $roomplan_data; } @@ -173,6 +225,8 @@ class StundenplanLib{ $this->_ci->load->config('calendar'); // Load Models $this->_ci->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->_ci->load->model('ressource/Reservierung_model', 'ReservierungModel'); + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); $is_mitarbeiter = getData($this->_ci->MitarbeiterModel->isMitarbeiter(getAuthUID())); @@ -186,7 +240,7 @@ class StundenplanLib{ if (isError($reservierungen)) return $reservierungen; - $function_error = $this->expand_object_information($reservierungen->retval); + $function_error = $this->expandObjectInformation($reservierungen->retval); if (!is_null($function_error)) return $function_error; @@ -228,9 +282,15 @@ class StundenplanLib{ return success($lektoren); } - public function expand_object_information($data){ + public function expandObjectInformation($data) + { $this->_ci =& get_instance(); + // Load Config + $this->_ci->load->config('calendar'); + // Load Model + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + foreach ($data as $item) { $tz = new DateTimeZone($this->_ci->config->item('timezone')); @@ -324,69 +384,64 @@ class StundenplanLib{ $ferienEvents = $this->_ci->FerienModel->execReadOnlyQuery(" SELECT * FROM lehre.tbl_ferien - WHERE (bisdatum >= ? AND vondatum <= ?) AND (studiengang_kz = 0 OR studiengang_kz = ?) - ",[$start_date, $end_date, $studiengang_kz]); + WHERE (bisdatum >= ? AND vondatum < ?) AND (studiengang_kz = 0 OR studiengang_kz = ?) + ", [$start_date, $end_date, $studiengang_kz]); - if (isError($ferienEvents)) { - return error(getData($ferienEvents)); - } + if (isError($ferienEvents)) + return $ferienEvents; + $ferienEvents = getData($ferienEvents); - - if(is_array($ferienEvents) && count($ferienEvents) > 0){ - - $ferienEvents = array_map(function($event){ - $event_start = new DateTime($event->vondatum); - $event_end = new DateTime($event->bisdatum); - $event_end->modify('+1 day'); - - $interval = new DateInterval('P1D'); - $period = new DatePeriod($event_start, $interval, $event_end); - $event->dates = iterator_to_array($period); - return $event; - }, $ferienEvents); - - $start_date = new DateTime($start_date); - $start_date->setTime(0, 0, 0); - $end_date = new DateTime($end_date); - $end_date->setTime(23, 59, 59); - $ferienEventsFlattened=[]; - foreach($ferienEvents as $ferien_event){ - foreach($ferien_event->dates as $date){ - if ($date < $start_date || $date > $end_date) - continue; - $event = new stdClass(); - $event->bezeichnung = $ferien_event->bezeichnung; - $event->datum = $date->format('Y-m-d'); - $event->type = 'ferien'; - $ferienEventsFlattened[] = $event; - } - }; - - $today=new DateTime(); - $ferienEventsFlattened = array_map(function($event) use($today, $tz){ - $ferien_event = (object) array( - 'type' => 'ferien', - 'beginn' => $today->format('H:i:s'), - 'ende' => $today->format('H:i:s'), - 'isostart' => (new DateTime($event->datum . ' 00:00:00', $tz))->format('c'), - 'isoend' => (new DateTime($event->datum . ' 23:59:59', $tz))->format('c'), - 'allDayEvent' => true, - 'datum' => $event->datum, - 'topic' => $event->bezeichnung, - 'titel' => $event->bezeichnung, - 'farbe' => '00689E' - ); - return $ferien_event; - }, $ferienEventsFlattened); - - return success($ferienEventsFlattened); - } - else{ + if (!$ferienEvents) return success([]); - } - + $ferienEvents = array_map(function ($event) { + $event_start = new DateTime($event->vondatum); + $event_end = new DateTime($event->bisdatum); + $event_end->modify('+1 day'); + + $interval = new DateInterval('P1D'); + $period = new DatePeriod($event_start, $interval, $event_end); + $event->dates = iterator_to_array($period); + return $event; + }, $ferienEvents); + + $start_date = new DateTime($start_date); + $start_date->setTime(0, 0, 0); + $end_date = new DateTime($end_date); + $end_date->setTime(23, 59, 59); + + $ferienEventsFlattened = []; + foreach ($ferienEvents as $ferien_event) { + foreach ($ferien_event->dates as $date) { + if ($date < $start_date || $date > $end_date) + continue; + $event = new stdClass(); + $event->bezeichnung = $ferien_event->bezeichnung; + $event->datum = $date->format('Y-m-d'); + $event->type = 'ferien'; + $ferienEventsFlattened[] = $event; + } + }; + + $today = new DateTime(); + $ferienEventsFlattened = array_map(function ($event) use ($today, $tz) { + $ferien_event = (object)array( + 'type' => 'ferien', + 'beginn' => $today->format('H:i:s'), + 'ende' => $today->format('H:i:s'), + 'isostart' => (new DateTime($event->datum . ' 00:00:00', $tz))->format('c'), + 'isoend' => (new DateTime($event->datum . ' 23:59:59', $tz))->format('c'), + 'allDayEvent' => true, + 'datum' => $event->datum, + 'topic' => $event->bezeichnung, + 'titel' => $event->bezeichnung, + 'farbe' => '00689E' + ); + return $ferien_event; + }, $ferienEventsFlattened); + + return success($ferienEventsFlattened); } // start of the private functions ######################################################################################################## @@ -437,8 +492,10 @@ class StundenplanLib{ - private function fetchBenutzerGruppenFromStudiensemester($semester_range){ - $student_uid = getAuthUID(); + private function fetchBenutzerGruppenFromStudiensemester($student_uid, $semester_range) + { + $this->_ci->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel'); + $benutzer_gruppen = []; // for each studiensemester fetch the benutzer gruppen and add them to an associate $bentuzer_gruppen array /* @@ -499,8 +556,10 @@ class StundenplanLib{ return success($benutzer_gruppen); } - private function fetchStudentlehrverbandFromStudiensemester($semester_range){ - $student_uid = getAuthUID(); + private function fetchStudentlehrverbandFromStudiensemester($student_uid, $semester_range) + { + $this->_ci->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel'); + $student_lehrverband = []; // for each studiensemester fetch the studentlehrverbaende and add them to an associate $student_lehrverband array /* @@ -566,7 +625,10 @@ class StundenplanLib{ return success($student_lehrverband); } - private function applyLoadUeberSemesterHaelfte(&$semester_range){ + private function applyLoadUeberSemesterHaelfte(&$semester_range) + { + $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + /* @var($semester_collection) convert the array of studiensemester into an associative array with the studiensemester as the key @@ -692,30 +754,29 @@ class StundenplanLib{ } } - private function studienSemesterErmitteln($start_date,$end_date){ - + private function studienSemesterErmitteln($start_date, $end_date) + { + $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + // gets all studiensemester from the student from start_date to end_date - $semester_range = $this->_ci->StudiensemesterModel->getByDateRange($start_date,$end_date); - if(isError($semester_range)) - { - return error(getData($semester_range)); - } - $semester_range = array_map( - function($sem) - { + $semester_range = $this->_ci->StudiensemesterModel->getByDateRange($start_date, $end_date); + if (isError($semester_range)) + return $semester_range; + + $semester_range = array_map( + function ($sem) { return $sem->studiensemester_kurzbz; }, getData($semester_range) ?: [] ); // if no studiensemester is found for the given timespan, get the nearest studiensemester - if(count($semester_range) == 0) + if (count($semester_range) == 0) { $aktuelle_studiensemester = $this->_ci->StudiensemesterModel->getNearest(); - if(isError($aktuelle_studiensemester)) - { - return error(getData($aktuelle_studiensemester)); - } + if (isError($aktuelle_studiensemester)) + return $aktuelle_studiensemester; + $aktuelle_studiensemester = getData($aktuelle_studiensemester); if (count($aktuelle_studiensemester) == 0) { return error("No aktuelles semester"); @@ -723,8 +784,8 @@ class StundenplanLib{ $aktuelle_studiensemester = current($aktuelle_studiensemester)->studiensemester_kurzbz; // push aktuelles semester in active semester array array_push($semester_range, $aktuelle_studiensemester); - } + return success($semester_range); } } diff --git a/public/js/api/factory/lvPlan.js b/public/js/api/factory/lvPlan.js index 99f7961f6..87e74cff5 100644 --- a/public/js/api/factory/lvPlan.js +++ b/public/js/api/factory/lvPlan.js @@ -30,8 +30,21 @@ export default { params: { start_date, end_date, lv_id } }; }, + eventsPersonal(start_date, end_date) { + return { + method: 'post', + url: '/api/frontend/v1/lvPlan/eventsPersonal', + params: { start_date, end_date } + }; + }, + eventsLv(lv_id, start_date, end_date) { + return { + method: 'post', + url: '/api/frontend/v1/lvPlan/eventsLv', + params: { lv_id, start_date, end_date } + }; + }, getStunden() { - // TODO(chris): seems to be called from nowhere? return { method: 'get', url: '/api/frontend/v1/LvPlan/Stunden' @@ -65,7 +78,7 @@ export default { }, LvPlanEvents(start_date, end_date, lv_id) { return { - method: 'get', + method: 'post', url: '/api/frontend/v1/LvPlan/LvPlanEvents', params: { start_date: start_date, From 30cc798c0b97853b5a50a554ec79ec498fe896f3 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Tue, 5 Aug 2025 08:35:37 +0200 Subject: [PATCH 3/7] Endpoint to get lv details --- .../controllers/api/frontend/v1/LvPlan.php | 36 +++++++++++++++++++ public/js/api/factory/lvPlan.js | 6 ++++ 2 files changed, 42 insertions(+) diff --git a/application/controllers/api/frontend/v1/LvPlan.php b/application/controllers/api/frontend/v1/LvPlan.php index b6c629fe1..3b6b55911 100644 --- a/application/controllers/api/frontend/v1/LvPlan.php +++ b/application/controllers/api/frontend/v1/LvPlan.php @@ -41,6 +41,7 @@ class LvPlan extends FHCAPI_Controller 'getLehreinheitStudiensemester' => self::PERM_LOGGED, 'studiensemesterDateInterval' => self::PERM_LOGGED, 'getLvPlanForStudiensemester' => self::PERM_LOGGED, + 'getLv' => self::PERM_LOGGED ]); $this->load->library('LogLib'); @@ -250,6 +251,41 @@ class LvPlan extends FHCAPI_Controller $this->terminateWithSuccess($result); } + /** + * get details for a lv + * @access public + * + * @param integer $lehrveranstaltung_id + * @return void + */ + public function getLv($lehrveranstaltung_id) + { + if (!$lehrveranstaltung_id && $lehrveranstaltung_id !== 0 && $lehrveranstaltung_id !== '0') + return show_404(); + + // Load Phrases + $this->loadPhrases(['lehre']); + + // Validation + $this->form_validation->set_data([ + 'lehrveranstaltung_id' => $lehrveranstaltung_id + ]); + + $this->form_validation->set_rules('lehrveranstaltung_id', $this->p->t('lehre', 'lehrveranstaltung_id'), 'integer'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + // Get Data + $this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); + + $result = $this->LehrveranstaltungModel->load($lehrveranstaltung_id); + + $result = $this->getDataOrTerminateWithError($result); + + return $this->terminateWithSuccess(current($result)); + } + /** * fetch moodle events * diff --git a/public/js/api/factory/lvPlan.js b/public/js/api/factory/lvPlan.js index 87e74cff5..0b179c9ba 100644 --- a/public/js/api/factory/lvPlan.js +++ b/public/js/api/factory/lvPlan.js @@ -87,4 +87,10 @@ export default { } }; }, + getLv(lehrveranstaltung_id) { + return { + method: 'get', + url: '/api/frontend/v1/LvPlan/getLv/' + lehrveranstaltung_id + }; + } }; \ No newline at end of file From 043c9fd5f39667769304ec55bc1946888d682b40 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Tue, 5 Aug 2025 09:33:11 +0200 Subject: [PATCH 4/7] split LvPlan into MyLvPlan (personal calendar) and LvPlan (lv calendar) --- application/config/routes.php | 1 + application/controllers/Cis/MyLvPlan.php | 39 +++++ public/js/apps/Dashboard/Fhc.js | 55 +++---- .../Cis/LvPlan/Lehrveranstaltung.js | 96 ++++++++++++ public/js/components/Cis/LvPlan/Personal.js | 143 ++++++++++++++++++ 5 files changed, 298 insertions(+), 36 deletions(-) create mode 100644 application/controllers/Cis/MyLvPlan.php create mode 100644 public/js/components/Cis/LvPlan/Lehrveranstaltung.js create mode 100644 public/js/components/Cis/LvPlan/Personal.js diff --git a/application/config/routes.php b/application/config/routes.php index 798d29ad0..af6b563d3 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -62,6 +62,7 @@ $route['api/v1/ressource/[B|b]etriebsmittelperson/(:any)'] = 'api/v1/ressource/b $route['api/v1/system/[S|s]prache/(:any)'] = 'api/v1/system/sprache2/$1'; $route['Cis/LvPlan/.*'] = 'Cis/LvPlan/index/$1'; +$route['Cis/MyLvPlan/.*'] = 'Cis/MyLvPlan/index/$1'; // load routes from extensions $subdir = 'application/config/extensions'; diff --git a/application/controllers/Cis/MyLvPlan.php b/application/controllers/Cis/MyLvPlan.php new file mode 100644 index 000000000..366ce8e65 --- /dev/null +++ b/application/controllers/Cis/MyLvPlan.php @@ -0,0 +1,39 @@ + ['basis/cis:r'] + ]); + + // Load Config + $this->load->config('calendar'); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * @return void + */ + public function index() + { + + $viewData = array( + 'uid'=>getAuthUID(), + 'timezone' => $this->config->item('timezone') + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'MyLvPlan']); + } +} diff --git a/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js index 075a399d8..b3ffa4315 100644 --- a/public/js/apps/Dashboard/Fhc.js +++ b/public/js/apps/Dashboard/Fhc.js @@ -3,7 +3,8 @@ import PluginsPhrasen from '../../plugins/Phrasen.js'; import Theme from '../../plugin/Theme.js'; import contrast from '../../directives/contrast.js'; import {setScrollbarWidth} from "../../helpers/CssVarCalcHelpers.js"; -import LvPlan, {DEFAULT_MODE_LVPLAN} from "../../components/Cis/LvPlan/LvPlan.js"; +import LvPlan from "../../components/Cis/LvPlan/Lehrveranstaltung.js"; +import MyLvPlan from "../../components/Cis/LvPlan/Personal.js"; import MylvStudent from "../../components/Cis/Mylv/Student.js"; import Profil from "../../components/Cis/Profil/Profil.js"; import Raumsuche from "../../components/Cis/Raumsuche/Raumsuche.js"; @@ -154,10 +155,14 @@ const router = VueRouter.createRouter({ path: "/Cis/LvPlan/:lv_id(\\d+)", name: "LvPlanOld", component: LvPlan, - redirect: (to) => { + redirect(to) { + const route = Vue.unref(router.currentRoute); + const { mode, focus_date } = route.params; // keep mode and focus_date if available return { // redirect to longer LvPlan url and map params name: "LvPlan", params: { + mode, + focus_date, lv_id: to.params.lv_id }, }; @@ -167,42 +172,20 @@ const router = VueRouter.createRouter({ path: `/Cis/LvPlan/:mode?/:focus_date?/:lv_id?`, name: 'LvPlan', component: LvPlan, - props: (route) => { // validate and set mode/focus date if for some reason missing - const validModes = ["Month", "Week", "Day"]; - - // check mode string - const mode = route.params.mode && - validModes.includes(route.params.mode.charAt(0).toUpperCase() + route.params.mode.slice(1).toLowerCase()) - ? route.params.mode.charAt(0).toUpperCase() + route.params.mode.slice(1).toLowerCase() - : DEFAULT_MODE_LVPLAN; - - // default to today date if not provided or string forms invalid date - const d = new Date(route.params.focus_date) - const focus_date = !isNaN(d) ? route.params.focus_date : new Date().toISOString().split("T")[0]; - // for consistency reasons format the props into one object but actually use a new name to we dont collide with - // existing viewData declaration written from codeigniter 3 into routerview tag + props(route) { return { - propsViewData: { - mode, - focus_date, - lv_id: route.params.lv_id - } + propsViewData: route.params + }; + } + }, + { + path: `/Cis/MyLvPlan/:mode?/:focus_date?`, + name: 'MyLvPlan', + component: MyLvPlan, + props(route) { + return { + propsViewData: route.params }; - }, - beforeEnter: (to, from, next) => { - // missing mode or focus_date -> set defaults - if (!to.params.mode || !to.params.focus_date) { - next({ - name: "LvPlan", - params: { - mode: to.params.mode || DEFAULT_MODE_LVPLAN, - focus_date: to.params.focus_date || new Date().toISOString().split("T")[0], - lv_id: to.params.lv_id - } - }); - } else { - next(); - } } }, { diff --git a/public/js/components/Cis/LvPlan/Lehrveranstaltung.js b/public/js/components/Cis/LvPlan/Lehrveranstaltung.js new file mode 100644 index 000000000..70773dce6 --- /dev/null +++ b/public/js/components/Cis/LvPlan/Lehrveranstaltung.js @@ -0,0 +1,96 @@ +import FhcCalendar from "../../Calendar/LvPlan.js"; + +import ApiLvPlan from '../../../api/factory/lvPlan.js'; +import ApiAuthinfo from '../../../api/factory/authinfo.js'; + +export const DEFAULT_MODE_LVPLAN = 'Week' + +export default { + name: 'LvPlanLehrveranstaltung', + components: { + FhcCalendar + }, + props: { + viewData: Object, // NOTE(chris): this is inherited from router-view + propsViewData: Object + }, + data() { + return { + lv: null + }; + }, + computed:{ + currentDay() { + if (!this.propsViewData?.focus_date || isNaN(new Date(this.propsViewData?.focus_date))) + return luxon.DateTime.now().setZone(this.viewData.timezone).toISODate(); + return this.propsViewData?.focus_date; + }, + currentMode() { + if (!this.propsViewData?.mode || !['day', 'week', 'month'].includes(this.propsViewData?.mode.toLowerCase())) + return DEFAULT_MODE_LVPLAN; + return this.propsViewData?.mode; + }, + currentLv() { + if (isNaN(parseInt(this.propsViewData?.lv_id))) + return null; + return this.propsViewData.lv_id; + } + }, + methods: { + handleChangeDate(day, newMode) { + return this.handleChangeMode(newMode, day); + }, + handleChangeMode(newMode, day) { + const mode = newMode[0].toUpperCase() + newMode.slice(1) + const focus_date = day.toISODate(); + + this.$router.push({ + name: "LvPlan", + params: { + mode, + focus_date, + lv_id: this.currentLv + } + }); + }, + getPromiseFunc(start, end) { + return [ + this.$api.call(ApiLvPlan.eventsLv(this.propsViewData.lv_id, start.toISODate(), end.toISODate())), + this.$api.call(ApiLvPlan.getLvPlanReservierungen(start.toISODate(), end.toISODate())) + ]; + } + }, + created() { + if (this.currentLv === null) + return; + this.$api + .call(ApiLvPlan.getLv(this.propsViewData?.lv_id)) + .then(res => { + this.lv = res.data; + }); + }, + template: /*html*/` +
+

+ {{ $p.t('lehre/stundenplan') }} + + {{ $p.user_language.value === 'German' ? lv.bezeichnung : lv.bezeichnung_english }} + +

+
+
+ {{ $p.t('lehre/noLvFound') }} +
+ +
` +}; diff --git a/public/js/components/Cis/LvPlan/Personal.js b/public/js/components/Cis/LvPlan/Personal.js new file mode 100644 index 000000000..5c4be5c23 --- /dev/null +++ b/public/js/components/Cis/LvPlan/Personal.js @@ -0,0 +1,143 @@ +import FhcCalendar from "../../Calendar/LvPlan.js"; + +import ApiLvPlan from '../../../api/factory/lvPlan.js'; +import ApiAuthinfo from '../../../api/factory/authinfo.js'; + +export const DEFAULT_MODE_LVPLAN = 'Week' + +export default { + name: 'LvPlanPersonal', + components: { + FhcCalendar + }, + props: { + viewData: Object, // NOTE(chris): this is inherited from router-view + propsViewData: Object + }, + data() { + return { + studiensemester_kurzbz: null, + studiensemester_start: null, + studiensemester_ende: null, + uid: null + }; + }, + computed:{ + currentDay() { + if (!this.propsViewData?.focus_date || isNaN(new Date(this.propsViewData?.focus_date))) + return luxon.DateTime.now().setZone(this.viewData.timezone).toISODate(); + return this.propsViewData?.focus_date; + }, + currentMode() { + if (!this.propsViewData?.mode || !['day', 'week', 'month'].includes(this.propsViewData?.mode.toLowerCase())) + return DEFAULT_MODE_LVPLAN; + return this.propsViewData?.mode; + }, + downloadLinks() { + if (!this.studiensemester_start || !this.studiensemester_ende || !this.uid) + return false; + + const opts = { zone: this.viewData.timezone }; + const start = luxon.DateTime + .fromISO(this.studiensemester_start, opts) + .toUnixInteger(); + const ende = luxon.DateTime + .fromISO(this.studiensemester_ende, opts) + .toUnixInteger(); + + const download_link = FHC_JS_DATA_STORAGE_OBJECT.app_root + + 'cis/private/lvplan/stpl_kalender.php' + + '?type=student' + + '&pers_uid=' + this.uid + + '&begin=' + start + + '&ende=' + ende; + + return [ + { title: "excel", icon: 'fa-solid fa-file-excel', link: download_link + '&format=excel' }, + { title: "csv", icon: 'fa-solid fa-file-csv', link: download_link + '&format=csv' }, + { title: "ical1", icon: 'fa-regular fa-calendar', link: download_link + '&format=ical&version=1&target=ical' }, + { title: "ical2", icon: 'fa-regular fa-calendar', link: download_link + '&format=ical&version=2&target=ical' } + ]; + } + }, + methods: { + handleChangeDate(day, newMode) { + return this.handleChangeMode(newMode, day); + }, + handleChangeMode(newMode, day) { + const mode = newMode[0].toUpperCase() + newMode.slice(1) + const focus_date = day.toISODate(); + + this.$router.push({ + name: "MyLvPlan", + params: { + mode, + focus_date + } + }); + }, + updateRange(rangeInterval) { + this.$api + .call(ApiLvPlan.studiensemesterDateInterval( + rangeInterval.end.startOf('week').toISODate() + )) + .then(res => { + this.studiensemester_kurzbz = res.data.studiensemester_kurzbz; + this.studiensemester_start = res.data.start; + this.studiensemester_ende = res.data.ende; + }); + }, + getPromiseFunc(start, end) { + return [ + this.$api.call(ApiLvPlan.eventsPersonal(start.toISODate(), end.toISODate())), + this.$api.call(ApiLvPlan.getLvPlanReservierungen(start.toISODate(), end.toISODate())) + ]; + } + }, + created() { + this.$api + .call(ApiAuthinfo.getAuthUID()) + .then(res => { + this.uid = res.data.uid; + }); + }, + template: /*html*/` +
+

+ {{ $p.t('lehre/stundenplan') }} + + {{ studiensemester_kurzbz }} + +

+
+ + + +
` +}; From aded9067e56971f9262294e11dae49073597bf04 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Tue, 5 Aug 2025 14:37:36 +0200 Subject: [PATCH 5/7] remove id-attribute from calendar renderer templates --- public/css/Cis4/CoreCalendarEvents.css | 60 ++++---- .../Cis/Renderer/Feiertage/calendarEvent.js | 8 +- .../Cis/Renderer/Lehreinheit/calendarEvent.js | 129 +++++++++++------- .../Renderer/Reservierungen/calendarEvent.js | 95 ++++++++++--- 4 files changed, 189 insertions(+), 103 deletions(-) diff --git a/public/css/Cis4/CoreCalendarEvents.css b/public/css/Cis4/CoreCalendarEvents.css index df451ebf1..3941872ef 100644 --- a/public/css/Cis4/CoreCalendarEvents.css +++ b/public/css/Cis4/CoreCalendarEvents.css @@ -4,96 +4,96 @@ height: 100%; } -/* Feiertag */ -.feiertagEventContent { +/* Feiertage */ +.cis-renderer-feiertage-calendar-event { align-items: center; color: var(--fhc-light); } -.monthPageContainer .feiertagEventContent, -.weekPageContainer .feiertagEventContent, -.dayPageContainer .feiertagEventContent { +.monthPageContainer .cis-renderer-feiertage-calendar-event, +.weekPageContainer .cis-renderer-feiertage-calendar-event, +.dayPageContainer .cis-renderer-feiertage-calendar-event { display: grid; grid-template-columns: auto 1fr; justify-items: center; } -.listPageContainer .feiertagEventContent { +.listPageContainer .cis-renderer-feiertage-calendar-event { display: flex; justify-content: center; } -.monthPageContainer .feiertagEventContent #ferienEventIcon { +.monthPageContainer .cis-renderer-feiertage-calendar-event .event-icon { margin: 0 .5rem; } -.weekPageContainer .feiertagEventContent #ferienEventIcon, -.dayPageContainer .feiertagEventContent #ferienEventIcon, -.listPageContainer .feiertagEventContent #ferienEventIcon { +.weekPageContainer .cis-renderer-feiertage-calendar-event .event-icon, +.dayPageContainer .cis-renderer-feiertage-calendar-event .event-icon, +.listPageContainer .cis-renderer-feiertage-calendar-event .event-icon { margin: .5rem; } -.listPageContainer .feiertagEventContent #ferienEventTitle { +.listPageContainer .cis-renderer-feiertage-calendar-event .event-title { flex-grow: 1; } /* Lehreinheit */ -.monthPageContainer .lehreinheitEventContent { +/* Reservierungen */ +.monthPageContainer .calendar-event-default { padding: 0!important; } -.monthPageContainer .lehreinheitEventContent #lehreinheitEventHeader, -.monthPageContainer .lehreinheitEventContent #lehreinheitLektoren, -.monthPageContainer .lehreinheitEventContent #lektorEllipsis { +.monthPageContainer .calendar-event-default .event-time, +.monthPageContainer .calendar-event-default .event-lectors { display: none!important; } -.monthPageContainer .lehreinheitEventContent #lehreinheitEventText { +.monthPageContainer .calendar-event-default .event-text { display: flex; justify-content: space-evenly; align-items: center; } -.weekPageContainer .lehreinheitEventContent { +.weekPageContainer .calendar-event-default { display: grid; grid-template-columns: auto 1fr; } -.weekPageContainer .lehreinheitEventContent #lehreinheitEventHeader { +.weekPageContainer .calendar-event-default .event-time { border-inline-end: solid 1px var(--bs-secondary); align-self: stretch; align-content: center; padding: .25em .5em .25em .25em; margin-inline-end: .25rem; } -.weekPageContainer .lehreinheitEventContent #lehreinheitEventText { +.weekPageContainer .calendar-event-default .event-text { display: flex; flex-direction: column; justify-content: space-evenly; align-items: center; } -.dayPageContainer .lehreinheitEventContent, -.listPageContainer .lehreinheitEventContent { +.dayPageContainer .calendar-event-default, +.listPageContainer .calendar-event-default { display: flex; align-items: center; } -.dayPageContainer .lehreinheitEventContent #lehreinheitEventHeader, -.listPageContainer .lehreinheitEventContent #lehreinheitEventHeader { +.dayPageContainer .calendar-event-default .event-time, +.listPageContainer .calendar-event-default .event-time { align-content: center; padding-inline-end: .5em; border-inline-end: solid 1px; margin-inline-end: .5em; } -.dayPageContainer .lehreinheitEventContent #lehreinheitEventText, -.listPageContainer .lehreinheitEventContent #lehreinheitEventText { +.dayPageContainer .calendar-event-default .event-text, +.listPageContainer .calendar-event-default .event-text { flex: 1 1 auto; display: flex; flex-wrap: wrap; gap: .25em; justify-content: center; } -.dayPageContainer .lehreinheitEventContent #lehreinheitTopic, -.dayPageContainer .lehreinheitEventContent #lehreinheitOrt, -.listPageContainer .lehreinheitEventContent #lehreinheitTopic, -.listPageContainer .lehreinheitEventContent #lehreinheitOrt { +.dayPageContainer .calendar-event-default .event-topic, +.dayPageContainer .calendar-event-default .event-place, +.listPageContainer .calendar-event-default .event-topic, +.listPageContainer .calendar-event-default .event-place { flex: 0 0 100%; text-align: center; } -.fhc-roominformation .lehreinheitEventContent #lehreinheitOrt { +.fhc-roominformation .calendar-event-default .event-place { display: none; } diff --git a/public/js/components/Cis/Renderer/Feiertage/calendarEvent.js b/public/js/components/Cis/Renderer/Feiertage/calendarEvent.js index ffc164117..d226e935a 100644 --- a/public/js/components/Cis/Renderer/Feiertage/calendarEvent.js +++ b/public/js/components/Cis/Renderer/Feiertage/calendarEvent.js @@ -7,8 +7,8 @@ export default { }, }, template: ` -
- - {{event.titel}} -
`, +
+ + {{ event.titel }} +
`, }; \ No newline at end of file diff --git a/public/js/components/Cis/Renderer/Lehreinheit/calendarEvent.js b/public/js/components/Cis/Renderer/Lehreinheit/calendarEvent.js index a334ea4d4..ca8d470e2 100644 --- a/public/js/components/Cis/Renderer/Lehreinheit/calendarEvent.js +++ b/public/js/components/Cis/Renderer/Lehreinheit/calendarEvent.js @@ -1,59 +1,92 @@ export default { - methods:{ - convertTime: function ([hour, minute]) { - let date = new Date(); - date.setHours(hour); - date.setMinutes(minute); - // returns date string as hh:mm - return date.toLocaleTimeString(this.$p.user_locale, { hour: '2-digit', minute: '2-digit', hour12: false }); - - }, - }, - computed:{ - calendarEventTooltip: function(){ - let lektorenEmpty = true; - let tooltipString = `${this.$p.t('global','uhrzeit')}: ${this.convertTime(this.event.beginn.split(":"))} / ${this.convertTime(this.event.ende.split(":")) }`; - - tooltipString += `\n${this.$p.t('profilUpdate', 'topic')}: ${this.event.topic}`; - tooltipString += `${this.$p.t('person', 'ort')}: ${this.event.ort_kurzbz}`; - if(Array.isArray(this.event.lektor) && this.event.lektor.length > 0){ - lektorenEmpty = false; - tooltipString += `\n${this.$p.t('lehre','lektor')}: `; - this.event.lektor.slice(0,3).forEach(lektor => { - tooltipString += `${lektor.kurzbz}\n`; - }) - if(this.event.lektor.length > 3){ - tooltipString += `${this.$p.t('lehre', 'weitereLektoren', [(this.event.lektor.length - 3)])}\n`; - } - } - if(lektorenEmpty){ - tooltipString += "\n"; - } - - - return tooltipString; - }, - }, props:{ event: { - type:Object, - required:true, + type: Object, + required: true + } + }, + computed:{ + tooltipString() { + const tooltipArray = []; + + tooltipArray.push([ + this.$p.t('global/uhrzeit'), + [this.start, this.end].join(' - ') + ].join(": ")); + + tooltipArray.push([ + this.$p.t('profilUpdate/topic'), + this.event.topic + ].join(": ")); + + tooltipArray.push([ + this.$p.t('person/ort'), + this.event.ort_kurzbz + ].join(": ")); + + this.event.lektor = [ + this.event.lektor[0], + this.event.lektor[0], + this.event.lektor[0], + this.event.lektor[0], + this.event.lektor[0], + ]; + + 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(": ")); + } else {console.log(this.event.lektor); + tooltipArray.push([ + this.$p.t('lehre/lektor'), + this.event.lektor.map(lektor => lektor.kurzbz).join("\n") + ].join(": ")); + } + } + + return tooltipArray.join("\n"); }, + start() { + return luxon.Duration + .fromISOTime(this.event.beginn) + .toISOTime({ suppressSeconds: true }); + }, + end() { + return luxon.Duration + .fromISOTime(this.event.ende) + .toISOTime({ suppressSeconds: true }); + } }, template: /*html*/` -
-
- {{convertTime(event.beginn.split(":"))}} - {{convertTime(event.ende.split(":"))}} +
+
+ {{ start }} + {{ end }}
-
- {{event.topic}} - {{event.ort_kurzbz}} - - {{lektor.kurzbz}} +
+ {{ event.topic }} + {{ event.ort_kurzbz }} + + {{ lektor.kurzbz }} + + + ... +{{ event.lektor.length - 3 }} - ...+ - {{event.lektor.length-3}}
`, diff --git a/public/js/components/Cis/Renderer/Reservierungen/calendarEvent.js b/public/js/components/Cis/Renderer/Reservierungen/calendarEvent.js index c6b8054c2..2447c4f61 100644 --- a/public/js/components/Cis/Renderer/Reservierungen/calendarEvent.js +++ b/public/js/components/Cis/Renderer/Reservierungen/calendarEvent.js @@ -1,30 +1,83 @@ export default { - methods: { - convertTime: function ([hour, minute]) { - let date = new Date(); - date.setHours(hour); - date.setMinutes(minute); - // returns date string as hh:mm - return date.toLocaleTimeString(this.$p.user_locale, { hour: '2-digit', minute: '2-digit', hour12: false }); - - }, - }, props: { event: { type: Object, - required: true, - }, + required: true + } }, - template: ` -
-
- {{convertTime(event.beginn.split(":"))}} - {{convertTime(event.ende.split(":"))}} + computed: { + tooltipString() { + const tooltipArray = []; + + tooltipArray.push([ + this.$p.t('global/uhrzeit'), + [this.start, this.end].join(' - ') + ].join(": ")); + + tooltipArray.push([ + this.$p.t('profilUpdate/topic'), + this.event.topic + ].join(": ")); + + tooltipArray.push([ + this.$p.t('person/ort'), + this.event.ort_kurzbz + ].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(": ")); + } else { + tooltipArray.push([ + this.$p.t('lehre/lektor'), + this.event.lektor.map(lektor => lektor.kurzbz).join("\n") + ].join(": ")); + } + } + + return tooltipArray.join("\n"); + }, + start() { + return luxon.Duration + .fromISOTime(this.event.beginn) + .toISOTime({ suppressSeconds: true }); + }, + end() { + return luxon.Duration + .fromISOTime(this.event.ende) + .toISOTime({ suppressSeconds: true }); + } + }, + template: /* html */` +
+
+ {{ start }} + {{ end }}
-
- {{event.topic}} - {{lektor.kurzbz}} - {{event.ort_kurzbz}} +
+ {{ event.topic }} + + {{ lektor.kurzbz }} + + + ... +{{ event.lektor.length - 3 }} + + {{ event.ort_kurzbz }}
`, From 6391e58f7466ef5c947061c4ecbc7e7b56fcac95 Mon Sep 17 00:00:00 2001 From: chfhtw Date: Tue, 5 Aug 2025 14:37:57 +0200 Subject: [PATCH 6/7] Bugfix: negation of instanceof --- .../js/components/Cis/Renderer/Reservierungen/modalContent.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/js/components/Cis/Renderer/Reservierungen/modalContent.js b/public/js/components/Cis/Renderer/Reservierungen/modalContent.js index 66428e37f..0d6c62672 100644 --- a/public/js/components/Cis/Renderer/Reservierungen/modalContent.js +++ b/public/js/components/Cis/Renderer/Reservierungen/modalContent.js @@ -34,7 +34,7 @@ export default { start_time: function () { if (!this.event.beginn) return 'N/A'; - if (!this.event.beginn instanceof Date) { + if (!(this.event.beginn instanceof Date)) { return this.event.beginn; } return numberPadding(this.event.beginn.getHours()) + ":" + numberPadding(this.event.beginn.getMinutes()); @@ -42,7 +42,7 @@ export default { end_time: function () { if (!this.event.ende) return 'N/A'; - if (!this.event.ende instanceof Date) { + if (!(this.event.ende instanceof Date)) { return this.event.ende; } return numberPadding(this.event.ende.getHours()) + ":" + numberPadding(this.event.ende.getMinutes()); From 603622a3f19aaa45b86c487ce49f1348dabf931e Mon Sep 17 00:00:00 2001 From: chfhtw Date: Tue, 5 Aug 2025 14:38:59 +0200 Subject: [PATCH 7/7] LvPlan use computed for lv title --- .../js/components/Cis/LvPlan/Lehrveranstaltung.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/public/js/components/Cis/LvPlan/Lehrveranstaltung.js b/public/js/components/Cis/LvPlan/Lehrveranstaltung.js index 70773dce6..4364a5df4 100644 --- a/public/js/components/Cis/LvPlan/Lehrveranstaltung.js +++ b/public/js/components/Cis/LvPlan/Lehrveranstaltung.js @@ -34,6 +34,17 @@ export default { if (isNaN(parseInt(this.propsViewData?.lv_id))) return null; return this.propsViewData.lv_id; + }, + lvTitle() { + if (this.currentLv === null) + return ''; + if (!this.lv) + return ''; + + if (this.$p.user_language.value === 'English') + return this.lv.bezeichnung_english; + + return this.lv.bezeichnung; } }, methods: { @@ -73,8 +84,8 @@ export default {

{{ $p.t('lehre/stundenplan') }} - - {{ $p.user_language.value === 'German' ? lv.bezeichnung : lv.bezeichnung_english }} + + {{ lvTitle }}