Merge branch 'feature-61230/FHC4_Studierendenverwaltung_LVTermine' into merge_FHC4_55354_55991_55992_60874_60875_61229_61230_61231

This commit is contained in:
Harald Bamberger
2025-05-21 16:25:36 +02:00
10 changed files with 995 additions and 11 deletions
@@ -160,6 +160,11 @@ class Config extends FHCAPI_Controller
'component' => './Stv/Studentenverwaltung/Details/JointStudies.js'
];
$result['coursedates'] = [
'title' => $this->p->t('stv', 'tab_courseDates'),
'component' => './Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine.js'
];
Events::trigger('stv_conf_student', function & () use (&$result) {
return $result;
});
@@ -0,0 +1,408 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class LvTermine extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'getStundenplan' => ['admin:r', 'assistenz:r'],
'getStudiensemester' => ['admin:r', 'assistenz:r'],
]);
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
$this->load->library('form_validation');
// Load language phrases
$this->loadPhrases([
'ui',
]);
// Load models
$this->load->model('ressource/Stundenplan_model', 'StundenplanModel');
//query verwenden wie im Cis endpoint
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$this->load->model('education/Studentlehrverband_model', 'StudentlehrverbandModel');
$this->load->model('person/Benutzergruppe_model', 'BenutzergruppeModel');
}
//TODO Build own lib or combine with Controller Stundenplan.php
//here use of logic of Stundenplan.php, extended with parameters uid, grouping, and used dbTable
public function getStundenplan($uid, $start_date = null, $end_date = null, $groupConsecutiveHours = false, $dbStundenplanTable = "stundenplan")
{
$student_uid = $uid;
$semester_range = $this->studienSemesterErmitteln($start_date, $end_date);
$this->sortStudienSemester($semester_range);
$this->applyLoadUeberSemesterHaelfte($semester_range);
$benutzer_gruppen = $this->fetchBenutzerGruppenFromStudiensemester($semester_range, $student_uid);
$student_lehrverband = $this->fetchStudentlehrverbandFromStudiensemester($semester_range, $student_uid);
if(!$groupConsecutiveHours)
$stundenplan_query = $this->StundenplanModel->getStundenplanQuery(
$start_date,
$end_date,
$semester_range,
$benutzer_gruppen,
$student_lehrverband
);
else
$stundenplan_query = $this->StundenplanModel->getStundenplanQuery(
$start_date,
$end_date,
$semester_range,
$benutzer_gruppen,
$student_lehrverband,
true,
$dbStundenplanTable
);
if(!$stundenplan_query)
{
$this->terminateWithSuccess([]);
}
if($groupConsecutiveHours)
{
$stundenplan_data = $this->StundenplanModel->stundenplanGruppierungConsecutive($stundenplan_query);
}
else
{
$stundenplan_data = $this->StundenplanModel->stundenplanGruppierung($stundenplan_query);
}
$stundenplan_data = $this->getDataOrTerminateWithError($stundenplan_data) ?? [];
$this->terminateWithSuccess($stundenplan_data);
$this->expand_object_information($stundenplan_data);
$this->returnObj['$stundenplan_query'] = $stundenplan_query;
$this->returnObj['$student_lehrverband'] = $student_lehrverband;
$this->returnObj['$benutzer_gruppen'] = $benutzer_gruppen;
$this->terminateWithSuccess($stundenplan_data);
}
public function getStudiensemester()
{
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$this->StudiensemesterModel->addOrder('studienjahr_kurzbz', 'DESC');
$result = $this->StudiensemesterModel->load();
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
//copied from Stundenplan.php
private function studienSemesterErmitteln($start_date, $end_date)
{
// gets all studiensemester from the student from start_date to end_date
$semester_range = $this->StudiensemesterModel->getByDateRange($start_date, $end_date);
$semester_range = array_map(
function ($sem) {
return $sem->studiensemester_kurzbz;
},
$this->getDataOrTerminateWithError($semester_range)
);
// if no studiensemester is found for the given timespan, get the nearest studiensemester
if(count($semester_range) == 0)
{
$aktuelle_studiensemester = $this->StudiensemesterModel->getNearest();
$aktuelle_studiensemester = $this->getDataOrTerminateWithError($aktuelle_studiensemester);
if (count($aktuelle_studiensemester) == 0) {
$this->terminateWithError("No aktuelles semester");
}
$aktuelle_studiensemester = current($aktuelle_studiensemester)->studiensemester_kurzbz;
// push aktuelles semester in active semester array
array_push($semester_range, $aktuelle_studiensemester);
}
return $semester_range;
}
//copied from Stundenplan.php
private function sortStudienSemester(&$semester_range)
{
usort(
$semester_range,
function ($first, $second) {
$sem_first = null;
$year_first = null;
$match_first = null;
$sem_second = null;
$year_second = null;
$match_second = null;
preg_match('/([WS]+)([0-9]+)/', $first, $match_first);
preg_match('/([WS]+)([0-9]+)/', $second, $match_second);
$sem_first = $match_first[1];
$year_first = intval($match_first[2]);
$sem_second = $match_second[1];
$year_second = intval($match_second[2]);
if($year_first < $year_second)
{
return -1;
}
elseif($year_first > $year_second)
{
return 1;
}
elseif($year_first == $year_second && $sem_first > $sem_second)
{
return 1;
}
elseif($year_first == $year_second && $sem_first < $sem_second)
{
return -1;
}
return 0;
}
);
}
//copied from Stundenplan.php
private function applyLoadUeberSemesterHaelfte(&$semester_range)
{
/*
@var($semester_collection)
convert the array of studiensemester into an associative array with the studiensemester as the key
and the values of each key are the studiensemester needed for the query associated to that studiensemester
example:
#INPUT:
['WS2023','SS2024','WS2024']
#OUTPUT:
[
'WS2023' => ['SS2023','WS2023']
'SS2024' => ['WS2023','SS2024']
'WS2024' => ['SS2024','WS2024']
]
*/
$semester_collection = [];
foreach($semester_range as $studiensemester)
{
$previous_studiensemester = $this->StudiensemesterModel->getPreviousFrom($studiensemester);
$previous_studiensemester = $this->getDataOrTerminateWithError($previous_studiensemester);
if (count($previous_studiensemester) == 0) {
$this->terminateWithError("No previous semester");
}
$previous_studiensemester = current($previous_studiensemester)->studiensemester_kurzbz;
$semester_collection[$studiensemester] = [$previous_studiensemester, $studiensemester];
}
/*
@var($studienSemesterDateRanges)
fetches for each studiensemester the start and end date, (SS) summer studiensemester are extended by 1 month to cover the summerbreak
based on the LVPLAN_LOAD_UEBER_SEMESTERHAELFTE constant it will load both the semester and the previous semester with the full date range
or the semester with the full date range and the previous semester with the half date range:
#INPUT:
[
'WS2023' => ['SS2023','WS2023']
'SS2024' => ['WS2023','SS2024']
'WS2024' => ['SS2024','WS2024']
]
#OUTPUT: depends whether LVPLAN_LOAD_UEBER_SEMESTERHAELFTE is true or false
~ if LVPLAN_LOAD_UEBER_SEMESTERHAELFTE == true
[
"SS2024": [
"WS2023": [
"start"=> "2024-02-03",
"ende"=> "2024-08-31"
],
"SS2024": [
"start"=> "2024-02-03",
"ende"=> "2024-08-31"
]
]
]
~ if LVPLAN_LOAD_UEBER_SEMESTERHAELFTE == false
[
"SS2024": [
"WS2023": [
"start"=> "2024-02-03",
"ende"=> "2024-05-17"
],
"SS2024": [
"start"=> "2024-02-03",
"ende"=> "2024-08-31"
]
]
]
*/
$studienSemesterDateRanges=[];
foreach($semester_collection as $semester_original => $semester_adjoint)
{
$semester_start_ende = $this->StudiensemesterModel->getStartEndeFromStudiensemester($semester_original);
$semester_start_ende = current($this->getDataOrTerminateWithError($semester_start_ende));
// initialize empty arrays to add key value pairs
$studienSemesterDateRanges[$semester_original] = [];
// check if the studiensemester is a summer semester and add 1 month to bridge the school summer break
$match = null;
preg_match("/^(SS)([0-9]+)/", $semester_original, $match);
if(count($match) >0)
{
$one_month = new DateInterval('P1M');
$one_day = DateInterval::createFromDateString('1 days');
$summer_studiensemester_end_date = DateTime::createFromFormat('Y-m-d', $semester_start_ende->ende);
$summer_studiensemester_end_date->add($one_month);
$summer_studiensemester_end_date->sub($one_day);
$semester_start_ende->ende = date_format($summer_studiensemester_end_date, 'Y-m-d');
}
if (defined('LVPLAN_LOAD_UEBER_SEMESTERHAELFTE') && LVPLAN_LOAD_UEBER_SEMESTERHAELFTE === true)
{
foreach($semester_adjoint as $adjoint)
{
$studienSemesterDateRanges[$semester_original][$adjoint]=$semester_start_ende;
}
}
else
{
//TODO: half of a DateInterval might not be correctly calculated
// calculate the half of the studiensemester
$studiensemester_start_date = DateTime::createFromFormat('Y-m-d', $semester_start_ende->start);
$studiensemester_end_date = DateTime::createFromFormat('Y-m-d', $semester_start_ende->ende);
$studiensemester_time_difference = $studiensemester_start_date->diff($studiensemester_end_date);
$half_dateNumber = ceil($studiensemester_time_difference->d/2)+ceil(($studiensemester_time_difference->m*30)/2);
$half_dateInterval = new DateInterval('P'.strval($half_dateNumber) .'D');
$studiensemester_half = date_format($studiensemester_start_date->add($half_dateInterval), 'Y-m-d');
$first_half = new stdClass();
$first_half->start = $semester_start_ende->start;
$first_half->ende = $studiensemester_half;
$studienSemesterDateRanges[$semester_original][$semester_adjoint[0]] = $first_half;
$studienSemesterDateRanges[$semester_original][$semester_adjoint[1]] = $semester_start_ende;
}
$semester_range = $studienSemesterDateRanges;
}
}
//copied from Stundenplan.php, extended with $student_uid
private function fetchBenutzerGruppenFromStudiensemester($semester_range, $student_uid)
{
//$student_uid = getAuthUID();
$benutzer_gruppen = [];
// for each studiensemester fetch the benutzer gruppen and add them to an associate $bentuzer_gruppen array
/*
[
['WS2023'] => [['gruppe1_SS2023','gruppe2_SS2023'],['gruppe1_WS2023','gruppe2_WS2023']],
['SS2024'] => [['gruppe1_WS2023','gruppe2_WS2023'],['gruppe1_SS2024','gruppe2_SS2024']],
['WS2024'] => [['gruppe1_SS2024','gruppe2_SS2024'],['gruppe1_WS2024','gruppe2_WS2024']],
]
*/
foreach($semester_range as $semester_key => $semester_array)
{
$benutzer_gruppen[$semester_key] = [];
// each semester could have ajoint semesters that need to be checked
foreach($semester_array as $semester => $semester_date_range)
{
// for each active semester query the benutzer_gruppen associated to the semester
$benutzer_query = $this->BenutzergruppeModel->execReadOnlyQuery("
SELECT * FROM tbl_benutzergruppe where uid = ? AND studiensemester_kurzbz = ?", [$student_uid, $semester]);
$benutzer_query_result = $this->getDataOrTerminateWithError($benutzer_query);
array_push(
$benutzer_gruppen[$semester_key],
array_map(
function ($item) {
return "'".$item->gruppe_kurzbz. "'";
},
$benutzer_query_result
)
);
}
}
// merge the gruppen of each studiensemester together for the original studiensemester
/*
[
['WS2023'] => ['gruppe1_SS2023','gruppe2_SS2023','gruppe1_WS2023','gruppe2_WS2023'],
['SS2024'] => ['gruppe1_WS2023','gruppe2_WS2023','gruppe1_SS2024','gruppe2_SS2024'],
['WS2024'] => ['gruppe1_SS2024','gruppe2_SS2024','gruppe1_WS2024','gruppe2_WS2024'],
]
*/
$benutzer_gruppen = array_map(
function ($gruppe) {
$merged_gruppe = [];
foreach($gruppe as $gruppen_array)
{
$merged_gruppe = array_merge($merged_gruppe, $gruppen_array);
}
return $merged_gruppe;
},
$benutzer_gruppen
);
return $benutzer_gruppen;
}
//copied from Stundenplan.php, extended with $student_uid
private function fetchStudentlehrverbandFromStudiensemester($semester_range, $student_uid)
{
//$student_uid = getAuthUID();
$student_lehrverband = [];
// for each studiensemester fetch the studentlehrverbaende and add them to an associate $student_lehrverband array
/*
[
['WS2023'] => [ [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ] ],
['SS2024'] => [ [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ], [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ] ],
['WS2024'] => [ [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ], [ ['stg_kz'=>298,'semester'=>3,'verband'=>"A",'gruppe'=>""] ] ],
]
*/
foreach($semester_range as $semester_key => $semester_array)
{
$student_lehrverband[$semester_key] = [];
foreach($semester_array as $semester => $semester_date_range)
{
// for each active semester query the student_lehrverband associated to the semester
$lehrverband_query = $this->BenutzergruppeModel->execReadOnlyQuery("
SELECT * FROM tbl_studentlehrverband where student_uid = ? AND studiensemester_kurzbz = ?", [$student_uid, $semester]);
$lehrverband_query_result = $this->getDataOrTerminateWithError($lehrverband_query);
array_push($student_lehrverband[$semester_key], array_map(
function ($item) {
$result = new stdClass();
$result->studiengang_kz = $item->studiengang_kz;
$result->semester = $item->semester;
$result->verband = $item->verband;
$result->gruppe = $item->gruppe;
return $result;
},
$lehrverband_query_result));
}
}
// merge the studentlehrverband of each studiensemester together for the original studiensemester
/*
[
['WS2023'] => [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""] ],
['SS2024'] => [ ['stg_kz'=>298,'semester'=>1,'verband'=>"A",'gruppe'=>""], ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""] ],
['WS2024'] => [ ['stg_kz'=>298,'semester'=>2,'verband'=>"A",'gruppe'=>""], ['stg_kz'=>298,'semester'=>3,'verband'=>"A",'gruppe'=>""] ],
]
*/
$student_lehrverband = array_map(
function ($studentlehrverband) {
$merged_studentlehrverband = [];
foreach($studentlehrverband as $studentlehrverband_array)
{
$merged_studentlehrverband = array_merge($merged_studentlehrverband, $studentlehrverband_array);
}
return $merged_studentlehrverband;
},
$student_lehrverband
);
return $student_lehrverband;
}
}
@@ -50,7 +50,6 @@ class Stundenplan_model extends DB_Model
*/
public function groupedCalendarEvents($ort_kurzbz,$start_date,$end_date){
$gruppierteEvents= $this->execReadOnlyQuery("
SELECT
@@ -186,6 +185,99 @@ class Stundenplan_model extends DB_Model
return $query_result;
}
/**
* groups rows of a subquery that fetches data from the lehre.vw_stundenplan table or lehre.vw_stundenplandev
* @param string $stundenplanViewQuery the subquery used to group the result regarding consecutive hours (Tab LV Termine)
*
* @return stdClass
*/
public function stundenplanGruppierungConsecutive($stundenplanViewQuery)
{
$query_result = $this->execReadOnlyQuery("
SELECT
distinct lehrveranstaltung_id,
datum,
MIN(beginn) as beginn,
MAX(ende) as ende,
type,
topic,
gruppe,
ort_kurzbz,
lehreinheit_id,
lehrfach_bez,
lektor,
lektorname,
gruppen_kuerzel,
farbe
FROM
(
SELECT
'lehreinheit' as type, beginn, ende, datum,
CONCAT(lehrfach,'-',lehrform) as topic,
array_agg(DISTINCT lektor) as lektor,
array_agg(DISTINCT lektorname) as lektorname,
array_agg(DISTINCT (gruppe,verband,semester,studiengang_kz,gruppen_kuerzel)) as gruppe,
array_agg(DISTINCT (gruppen_kuerzel)) as gruppen_kuerzel,
string_agg(DISTINCT ort_kurzbz, '/') as ort_kurzbz,
array_agg(DISTINCT lehreinheit_id) as lehreinheit_id,
titel, lehrfach, lehrform, lehrfach_bez, organisationseinheit, farbe, lehrveranstaltung_id
FROM
(
SELECT unr,datum,beginn, ende,
CASE
WHEN sp.mitarbeiter_kurzbz IS NOT NULL THEN sp.mitarbeiter_kurzbz
ELSE lektor
END as lektor,
CASE
WHEN gruppe_kurzbz IS NOT NULL THEN gruppe_kurzbz
ELSE (SELECT UPPER(typ || kurzbz)
FROM public.tbl_studiengang
WHERE studiengang_kz=sp.studiengang_kz) || COALESCE(sp.semester,'0') || COALESCE(sp.verband,'') || COALESCE(sp.gruppe,'')
END as gruppen_kuerzel,
(SELECT bezeichnung
FROM public.tbl_organisationseinheit
WHERE oe_kurzbz IN(
SELECT oe_kurzbz
FROM lehre.tbl_lehrveranstaltung
WHERE lehrveranstaltung_id = sp.lehrveranstaltung_id
)) as organisationseinheit,
ort_kurzbz, studiengang_kz, titel,lehreinheit_id,lehrfach_id,sp.anmerkung,fix,lehrveranstaltung_id,
stg_kurzbzlang,stg_bezeichnung,stg_typ,fachbereich_kurzbz,lehrfach,lehrfach_bez,farbe,lehrform,
anmerkung_lehreinheit,gruppe, verband, semester,stg_kurzbz,
CONCAT(p.nachname, ' ', p.vorname) as lektorname
FROM (".$stundenplanViewQuery.") sp
JOIN lehre.tbl_stunde ON lehre.tbl_stunde.stunde = sp.stunde
LEFT JOIN public.tbl_benutzer bn ON bn.uid = sp.uid
LEFT JOIN public.tbl_person p ON p.person_id = bn.person_id
) as subquery
GROUP BY unr, datum, beginn, ende, ort_kurzbz, titel, lehrform, lehrfach, lehrfach_bez, organisationseinheit,
farbe, lehrveranstaltung_id
ORDER BY datum, beginn) t
GROUP BY
lehrveranstaltung_id,
type,
datum,
topic,
lektor,
lehrfach_bez,
gruppe,
ort_kurzbz,
lehreinheit_id,
lektorname,
gruppen_kuerzel,
farbe
ORDER BY
datum, beginn
"
);
return $query_result;
}
/**
* queries Stundenplan but for a whole lva, irrespective of who is requesting it
*
@@ -300,10 +392,13 @@ class Stundenplan_model extends DB_Model
/**
* NO STANDALONE FUNCTION - Generates a SQL query string to fetch 'stundenplan' events for a specific student within the current semester.
*
* @param isLvList if condition needed for Tab LV Termine is given
* @param db_stpl_table enables switch to db 'stundenplandev'
*
* @return mixed
*/
public function getStundenplanQuery($start_date, $end_date,$semester,$gruppen,$studentlehrverbaende){
public function getStundenplanQuery($start_date, $end_date, $semester, $gruppen, $studentlehrverbaende, $isLvList=false, $db_stpl_table='stundenplan'){
// helper function to check if either $gruppen or $studentlehrverbaende are empty for each semester
$emptyCheck = function($toBeCheckedArray) use ($semester){
$result = true;
@@ -325,7 +420,7 @@ class Stundenplan_model extends DB_Model
$query =
"select sp.*
from lehre.vw_stundenplan sp
from lehre.vw_".$db_stpl_table." sp
WHERE
sp.datum >= ".$this->escape($start_date)."
AND sp.datum <= ".$this->escape($end_date);
@@ -335,10 +430,10 @@ class Stundenplan_model extends DB_Model
{
$query .= " AND ( ";
}
foreach($semester as $sem => $semester_date_range)
{
foreach($semester_date_range as $sem_date => $sem_date_range)
{
// if there are not groups for the semester skip the iteration step
@@ -358,7 +453,13 @@ class Stundenplan_model extends DB_Model
{
$query = substr($query, 0, -2);
}
//Condition for showLVList FHC4
if(!$isLvList)
$stringGroupLv = "AND gruppe_kurzbz is null";
else
$stringGroupLv ="";
foreach($semester as $sem=>$semester_date_range)
{
foreach($semester_date_range as $sem_date => $sem_date_range)
@@ -373,10 +474,10 @@ class Stundenplan_model extends DB_Model
// Eintraege fuer den ganzen Verband
$query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND sp.verband = ".$this->escape($lehrverband->verband)." AND (sp.gruppe is null OR sp.gruppe='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).")";
// Eintraege fuer das ganze Semester
$query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND (sp.verband is null OR sp.verband='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).") AND gruppe_kurzbz is null)";
$query .= "OR (sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND (sp.verband is null OR sp.verband='') AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)
." AND ".$this->escape($sem_date_range->ende).")". $stringGroupLv. ")";
$query .="OR";
}
}
}
@@ -434,5 +535,4 @@ class Stundenplan_model extends DB_Model
return $this->execQuery($query, [$uid, $uid]);
}
}
+4
View File
@@ -78,6 +78,10 @@ html {
overflow: visible !important;
}
.highlight-row {
background-color: #e5aeae !important;
}
@media (min-width: 768px) {
#sidebarMenu {
visibility: visible!important;
+35
View File
@@ -0,0 +1,35 @@
/**
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export default {
getCourselist(params) {
return {
method: 'get',
url: 'api/frontend/v1/stv/LvTermine/getStundenplan/' + params.student_uid + '/'
+ params.start_date + '/'
+ params.end_date + '/'
+ params.group_consecutiveHours + '/'
+ params.dbStundenplanTable
};
},
getStudiensemester(){
return {
method: 'get',
url: 'api/frontend/v1/stv/LvTermine/getStudiensemester/'
};
},
}
+2
View File
@@ -15,6 +15,7 @@ import archiv from './stv/archiv.js';
import documents from './stv/documents.js';
import exemptions from './stv/exemptions.js';
import jointstudies from "./stv/jointstudies.js";
import courselist from './stv/courselist.js';
export default {
verband,
@@ -34,6 +35,7 @@ export default {
documents,
exemptions,
jointstudies,
courselist,
configStudent() {
return this.$fhcApi.get('api/frontend/v1/stv/config/student');
},
+15
View File
@@ -0,0 +1,15 @@
export default {
getCourselist(url, config, params) {
//corresponding logic controller Stundenplan.php
return this.$fhcApi.get('api/frontend/v1/stv/LvTermine/getStundenplan/'
+ params.student_uid + '/'
+ params.start_date + '/'
+ params.end_date + '/'
+ params.group_consecutiveHours + '/'
+ params.dbStundenplanTable
);
},
getStudiensemester(){
return this.$fhcApi.get('api/frontend/v1/stv/LvTermine/getStudiensemester/');
},
}
@@ -0,0 +1,18 @@
import TableLvList from "./Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js";
export default {
name: "TabCourseList",
components: {
TableLvList
},
props: {
modelValue: Object,
},
data(){
return {}
},
template: `
<div class="stv-details-course-list h-100 d-flex flex-column">
<table-lv-list ref="tbl_course_list" :student="modelValue"></table-lv-list>
</div>`
};
@@ -0,0 +1,195 @@
import {CoreFilterCmpt} from "../../../../filter/Filter.js";
import FormInput from "../../../../Form/Input.js";
import FormForm from '../../../../Form/Form.js';
import ApiStvCoursedates from "../../../../../api/factory/stv/coursedates.js";
export default {
name: "TblCourseList",
components: {
CoreFilterCmpt,
FormInput,
FormForm
},
computed: {
downloadLink: function(){
if(!this.dataSem.start || !this.dataSem.ende || !this.student.uid) return;
let start = new Date(this.dataSem.start);
start = Math.floor(start.getTime()/1000);
let ende = new Date(this.dataSem.ende);
ende = Math.floor(ende.getTime() / 1000);
let link =
FHC_JS_DATA_STORAGE_OBJECT.app_root + "cis/private/lvplan/stpl_kalender.php?type=student&pers_uid=" + this.student.uid + "&begin=" + start + "&ende= " +ende + "&format=excel";
return link;
},
dbStundenplanTable: function (){
return this.showStundenplanDev ? 'stundenplandev' : 'stundenplan';
}
},
inject: {
currentSemester: {
from: 'currentSemester',
},
},
props: {
student: Object
},
data(){
return {
tabulatorOptions: null,
tabulatorEvents: [],
listStudiensemester: [],
dataSem: {},
showStundenplanDev: false
};
},
methods: {
initTabulatorOptions(){
this.tabulatorOptions = {
ajaxURL: 'dummy',
ajaxRequestFunc: () => this.$api.call(
ApiStvCoursedates.getCourselist({
student_uid: this.student.uid,
start_date: this.dataSem.start,
end_date: this.dataSem.ende,
group_consecutiveHours: true,
dbStundenplanTable: this.dbStundenplanTable})
),
ajaxResponse: (url, params, response) => {
return response.data;
},
columns: [
{title: "lv_id", field: "lehrveranstaltung_id", visible: false},
{title: "lehreinheit_id", field: "lehreinheit_id", visible: false},
{title: "datum", field: "datum",
formatter: function (cell) {
const dateStr = cell.getValue();
if (!dateStr) return "";
const date = new Date(dateStr);
return date.toLocaleString("de-DE", {
day: "2-digit",
month: "2-digit",
year: "numeric",
hour12: false
});
}},
{title: "beginn", field: "beginn"},
{title: "ende", field: "ende"},
{title: "farbe", field: "farbe", visible: false},
{title: "Gruppen", field: "gruppen_kuerzel"},
{title: "ort", field: "ort_kurzbz"},
{title: "lektorIn", field: "lektorname"},
{title: "Lehrfach", field: "lehrfach_bez"}
],
rowFormatter: function(row){
var data = row.getData();
//highlight background of row if color red in table
if(data.farbe == "A4A7FC"){
let el = row.getElement();
row.getElement().classList.add("highlight-row");
row.getElement().classList.remove("tabulator-row-odd");
row.getElement().classList.remove("tabulator-row-even");
}
}
};
this.tabulatorEvents = [
{
event: 'tableBuilt',
handler: async() => {
await this.$p.loadCategory(['global', 'ui', 'lehre']);
let cm = this.$refs.table.tabulator.columnManager;
cm.getColumnByField('lehrveranstaltung_id').component.updateDefinition({
title: this.$p.t('lehre', 'lehrveranstaltung_id')
});
cm.getColumnByField('lehreinheit_id').component.updateDefinition({
title: this.$p.t('global', 'lehreinheit_id')
});
cm.getColumnByField('datum').component.updateDefinition({
title: this.$p.t('global', 'datum')
});
cm.getColumnByField('beginn').component.updateDefinition({
title: this.$p.t('ui', 'dateFrom')
});
cm.getColumnByField('ende').component.updateDefinition({
title: this.$p.t('ui', 'dateTo')
});
cm.getColumnByField('gruppen_kuerzel').component.updateDefinition({
title: this.$p.t('global', 'gruppen')
});
cm.getColumnByField('ort_kurzbz').component.updateDefinition({
title: this.$p.t('global', 'ortLocation')
});
cm.getColumnByField('lektorname').component.updateDefinition({
title: this.$p.t('lehre', 'lektor')
});
cm.getColumnByField('lehrfach_bez').component.updateDefinition({
title: this.$p.t('global', 'lehrfach')
});
}
}
];
},
getDatesOfSemester(studiensemester_kurzbz) {
this.dataSem = this.listStudiensemester.find(item => item.studiensemester_kurzbz === studiensemester_kurzbz);
},
exportToExcel(){
window.open(this.downloadLink, '_blank');
},
reload() {
this.$refs.table.reloadTable();
},
switchStundenplan(){
this.showStundenplanDev = !this.showStundenplanDev;
this.reload();
}
},
watch: {
currentSemester(newVal, oldVal) {
this.getDatesOfSemester(newVal);
},
},
created(){
this.$api
.call(ApiStvCoursedates.getStudiensemester())
.then(result => {
this.listStudiensemester = result.data;
this.getDatesOfSemester(this.currentSemester);
this.initTabulatorOptions();
})
.catch(this.$fhcAlert.handleSystemError);
},
template: `
<div class="stv-details-courselist h-100 pb-3">
<h4>{{$p.t('global', 'termine')}}</h4>
<core-filter-cmpt
v-if="tabulatorOptions"
ref="table"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
table-only
:side-menu="false"
reload
>
<template #actions>
<button
class="btn btn-outline-secondary"
@click="exportToExcel">
{{$p.t('ui', 'export')}}
</button>
<button
class="btn btn-outline-secondary"
@click="switchStundenplan">
<span v-if="!showStundenplanDev">{{$p.t('lehre', 'stundenplan')}}</span>
<span v-else>{{$p.t('lehre', 'stundenplanDev')}}</span>
</button>
</template>
</core-filter-cmpt>
</div>
`
}
+202
View File
@@ -43089,6 +43089,208 @@ and represent the current state of research on the topic. The prescribed citatio
)
),
// FHC4 JOINT STUDIES END ----------------------------------------------------------------------------------------
// FHC 4 Lehrveranstaltungstermine START ---------------------------------------------------------------------------
array(
'app' => 'core',
'category' => 'stv',
'phrase' => 'tab_courseDates',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'LV Termine',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Course Dates',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'export',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Exportieren',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Export',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'lehre',
'phrase' => 'stundenplanDev',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Stundenplan DEV',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Timetable DEV',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'global',
'phrase' => 'lehreinheit_id',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Lehreinheit ID',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Teaching Unit ID',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'dateFrom',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'von',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'from',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'dateTo',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'bis',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'to',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'global',
'phrase' => 'gruppen',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Gruppen',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'groups',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'global',
'phrase' => 'ortLocation',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Ort',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'location',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'global',
'phrase' => 'lehrfach',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Lehrfach',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'subject',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'global',
'phrase' => 'termine',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Termine',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Dates',
'description' => '',
'insertvon' => 'system'
)
)
),
// FHC 4 Lehrveranstaltungstermine ENDE ---------------------------------------------------------------------------
);