Compare commits

...
Author SHA1 Message Date
Johann Hoffmann a765de11ef added missing space 2026-09-03 10:46:36 +02:00
Johann Hoffmann fe65dc60c4 finalized optional Studiengang Ansprechpartner Infoblock in Cis4 Studium page; 2026-09-02 18:13:41 +02:00
Johann Hoffmann f15349029f WIP stg info sidebar in cis4 studium 2026-09-02 09:30:57 +02:00
Harald Bamberger 6d641bbd06 pass in uid by reference 2026-08-24 13:56:55 +02:00
Harald Bamberger 3455aed3f5 Merge branch 'bhdev_master_stundenplan' 2026-08-24 13:46:09 +02:00
Harald Bamberger f84d12277d remove debug code 2026-08-24 07:31:47 +02:00
Harald Bamberger 9bf5bc2ad9 more generic bugfix, to use studentlehrverband only with date_range for the same studiensemester_kurzbz 2026-08-24 07:26:12 +02:00
Harald Bamberger 27765606e3 bufix akadGrad by sex if exists 2026-08-20 19:31:37 +02:00
Harald Bamberger 75d2cabdbe bugfix lv-plan 2026-08-20 15:10:26 +02:00
Harald Bamberger bae9d6d9a0 Merge branch 'feature-78257/StudVW_Und_Tags_Finetuning' 2026-08-19 17:11:12 +02:00
Harald Bamberger 43d6a882ce add padding to tags buttons, remove orphanded template closing tag 2026-08-19 17:07:25 +02:00
Harald Bamberger 7f3b4100ab Merge branch 'master' into feature-78257/StudVW_Und_Tags_Finetuning 2026-08-19 15:07:07 +02:00
Harald Bamberger 9f54ecce54 Merge branch 'epic/LVEvaluierung-Neu' 2026-08-19 13:59:00 +02:00
Cristina 7af0f4a478 Merge remote-tracking branch 'origin/epic/LVEvaluierung-Neu' into epic/LVEvaluierung-Neu 2026-08-19 13:35:25 +02:00
Cristina 0f843db33d Merge branch 'master' into epic/LVEvaluierung-Neu 2026-08-19 13:34:53 +02:00
Cristina 3e59648d5b Merge branch 'master' into epic/LVEvaluierung-Neu 2026-08-19 12:55:38 +02:00
Cristina 5923991848 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-08-19 12:55:03 +02:00
Harald Bamberger 55a6ec9d0d fix handling of grundbetrag and betrag_valorisiert 2026-08-19 11:48:22 +02:00
chfhtw 78505589c8 Bugfix: racecondition renderers 2026-08-19 09:45:15 +02:00
Cristina 5e15d4b219 Add Distinct to getLeitung in Studiengang_model.php
Avoid multiple records for same active STGL.
e.g. double entries
2026-08-18 16:51:39 +02:00
ma0068 afb8011347 bugfix manual rebuilding of Tag ZGV Missing 2026-08-13 12:57:49 +02:00
ma0068 15beaa9be8 Merge branch 'feature-78257/StudVW_Und_Tags_Finetuning' of github.com:FH-Complete/FHC-Core into feature-78257/StudVW_Und_Tags_Finetuning 2026-08-12 12:42:10 +02:00
ma0068 574057da88 add masterzgv to CoremissingZgvLib 2026-08-12 12:41:39 +02:00
Harald Bamberger a5797a0bde Merge branch 'master' into feature-78257/StudVW_Und_Tags_Finetuning 2026-08-11 18:00:17 +02:00
Cristina 37d5f2da5d Merge branch 'master' into epic/LVEvaluierung-Neu 2026-08-11 15:45:27 +02:00
Cristina 27c39cfdca Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-08-11 15:45:08 +02:00
ma0068 06895510e0 add reloadList if language is changed 2026-08-10 14:25:07 +02:00
ma0068 83b06b6c50 - Redesign Tags
- use Slot in Filter Component
- use Phrase  for relaoding Tag in Detail Header
2026-08-10 14:04:45 +02:00
Cristina eeb1529b64 Merge branch 'master' into epic/LVEvaluierung-Neu 2026-08-10 12:07:45 +02:00
Cristina 98c3707802 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-08-10 12:07:01 +02:00
Cristina e5c8807f17 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-08-05 15:13:35 +02:00
24 changed files with 544 additions and 195 deletions
@@ -114,6 +114,7 @@ class LvPlan extends FHCAPI_Controller
// fetching lvplan events
$result = $this->stundenplanlib->getEventsUser($start_date, $end_date, $uid);
$lvplanEvents = $this->getDataOrTerminateWithError($result);
// fetching moodle events
@@ -44,14 +44,29 @@ class Studgang extends FHCAPI_Controller
// Public methods
public function getStudiengangInfo(){
$isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID());
$isMitarbeiter = $this->getDataOrTerminateWithError($isMitarbeiter);
if($isMitarbeiter) {
$this->terminateWithSuccess(null);
$studiengang_kz = $this->input->get('studiengang_kz', true);
$semester = $this->input->get('semester', true);
// without a Studiengang the info of the logged in Student is returned
if (!is_numeric($studiengang_kz))
{
$isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID());
$isMitarbeiter = $this->getDataOrTerminateWithError($isMitarbeiter);
if($isMitarbeiter) {
$this->terminateWithSuccess(null);
}
$studiengang_kz = null;
$semester = null;
}
else
{
$studiengang_kz = (int)$studiengang_kz;
$semester = is_numeric($semester) ? (int)$semester : null;
}
// fetches the Studiengang Information which is used next to the news
$studiengangInfo = $this->StudiengangModel->getStudiengangInfoForNews();
$studiengangInfo = $this->StudiengangModel->getStudiengangInfoForNews($studiengang_kz, $semester);
$studiengangInfo= $this->getDataOrTerminateWithError($studiengangInfo);
$this->terminateWithSuccess($studiengangInfo);
}
+3 -2
View File
@@ -94,13 +94,13 @@ class StundenplanLib
if (isError($benutzer_gruppen))
return $benutzer_gruppen;
$benutzer_gruppen = getData($benutzer_gruppen);
$this->_ci->addMeta('spezialgruppen', $benutzer_gruppen);
// 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);
$this->_ci->addMeta('studentlehrvebaende', $student_lehrverband);
$stundenplan_query = $this->_ci->StundenplanModel->getStundenplanQuery(
$start,
$end,
@@ -632,6 +632,7 @@ class StundenplanLib
$result->semester = $item->semester;
$result->verband = $item->verband;
$result->gruppe = $item->gruppe;
$result->studiensemester_kurzbz = $item->studiensemester_kurzbz;
return $result;
},
$lehrverband_query_result);
@@ -28,10 +28,21 @@ class CoreMissingZgvTagLib
$this->ci->PrestudentModel->addJoin('public.tbl_prestudentstatus', 'prestudent_id');
$this->ci->PrestudentModel->addJoin('public.tbl_benutzer bn', 'person_id');
$this->ci->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz');
$this->ci->PrestudentModel->db->group_start();
$this->ci->PrestudentModel->db->where('zgvdatum', null);
$this->ci->PrestudentModel->db->where('typ', 'b');
$this->ci->PrestudentModel->db->or_group_start();
$this->ci->PrestudentModel->db->where('zgvmadatum', null);
$this->ci->PrestudentModel->db->where('typ', 'm');
$this->ci->PrestudentModel->db->group_end();
$this->ci->PrestudentModel->db->group_end();
$result = $this->ci->PrestudentModel-> loadWhere(array(
'bn.aktiv' => true, //check if necessary
'zgvdatum' => null,
'typ' => 'b',
'bn.aktiv' => true,
'studiensemester_kurzbz' => $semester
));
@@ -60,16 +71,36 @@ class CoreMissingZgvTagLib
$semester = $params['studiensemester_kurzbz'];
$prestudent_id = $params['id'];
$this->ci->PrestudentModel->addSelect('prestudent_id');
$this->ci->PrestudentModel->addSelect('start as von');
$this->ci->PrestudentModel->addSelect('ende as bis');
$this->ci->PrestudentModel->addJoin('public.tbl_prestudentstatus', 'prestudent_id');
//add studiensemester also here for manual rebuild
$this->ci->PrestudentModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
$this->ci->PrestudentModel->addJoin('public.tbl_benutzer bn', 'person_id');
$this->ci->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz');
$result = $this->ci->PrestudentModel->loadWhere(array(
'bn.aktiv' => true, //check if necessary
'zgvdatum' => null,
'typ' => 'b',
$this->ci->PrestudentModel->db->group_start();
$this->ci->PrestudentModel->db->where('zgvdatum', null);
$this->ci->PrestudentModel->db->where('typ', 'b');
$this->ci->PrestudentModel->db->or_group_start();
$this->ci->PrestudentModel->db->where('zgvmadatum', null);
$this->ci->PrestudentModel->db->where('typ', 'm');
$this->ci->PrestudentModel->db->group_end();
$this->ci->PrestudentModel->db->group_end();
$this->ci->PrestudentModel->db->limit(1);
$result = $this->ci->PrestudentModel-> loadWhere(array(
'bn.aktiv' => true,
'studiensemester_kurzbz' => $semester,
'prestudent_id' => $prestudent_id
));
if(hasData($result))
{
return $result;
@@ -225,6 +225,10 @@ class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializabl
$grundbetrag = number_format($grundbetrag, 2, '.', '');
}
$this->markDirty('grundbetrag', $this->grundbetrag, $grundbetrag);
if(in_array('grundbetrag', $this->modifiedcolumns))
{
$this->setBetrag_valorisiert($grundbetrag);
}
$this->grundbetrag = $grundbetrag;
return $this;
}
+1 -1
View File
@@ -204,7 +204,7 @@ class Student_model extends DB_Model
Events::trigger(
'generate_student_uid',
function ($value) use ($uid) {
function ($value) use (&$uid) {
$uid = $value;
},
$stgkzl,
@@ -457,6 +457,7 @@ class Studiengang_model extends DB_Model
*/
public function getLeitung($studiengang_kz = null)
{
$this->addDistinct();
$this->addSelect('uid, studiengang_kz, oe_kurzbz, vorname, nachname, email, titelpre, titelpost, alias');
$this->addJoin('public.tbl_benutzerfunktion', 'oe_kurzbz');
$this->addJoin('public.tbl_benutzer', 'uid');
@@ -652,31 +653,42 @@ class Studiengang_model extends DB_Model
}
/**
* Gets the Studiengang information. Without parameters it uses the Studiengang
* of the logged in Student.
*
* @param int|null $studiengang_kz
* @param int|null $semester used for the Jahrgangsvertretung
* @return stdClass
*/
public function getStudiengangInfoForNews()
public function getStudiengangInfoForNews($studiengang_kz = null, $semester = null)
{
$this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel');
$this->load->model('person/Person_model', 'PersonModel');
$this->load->model('crm/Student_model', 'StudentModel');
$student = $this->StudentModel->loadWhere(['student_uid' => getAuthUID()]);
if (isError($student))
return error($student);
if (getData($student)) {
$student = current(getData($student));
$studiengang_kz = $student->studiengang_kz;
$semester = $student->semester;
if (is_null($studiengang_kz))
{
$student = $this->StudentModel->loadWhere(['student_uid' => getAuthUID()]);
if (isError($student))
return error($student);
if (getData($student)) {
$student = current(getData($student));
$studiengang_kz = $student->studiengang_kz;
$semester = $student->semester;
}
}
// users without a Student record get no information instead of an error
if (is_null($studiengang_kz))
return success(null);
$stg_obj = $this->load($studiengang_kz);
if(isError($stg_obj))
return error($stg_obj);
if(getData($stg_obj))
{
$stg_obj = current(getData($stg_obj));
}
if(!hasData($stg_obj))
return error('Studiengang nicht gefunden');
$stg_obj = current(getData($stg_obj));
$stg_ltg = $this->getLeitungDetailed($stg_obj->studiengang_kz);
if (isError($stg_ltg))
@@ -604,11 +604,17 @@ class Stundenplan_model extends DB_Model
{
foreach($semester_date_range as $sem_date => $sem_date_range)
{
if(!array_key_exists($sem_date,$studentlehrverbaende) || count($studentlehrverbaende[$sem_date]) == 0)
if(!array_key_exists($sem,$studentlehrverbaende) || count($studentlehrverbaende[$sem]) == 0)
{
continue;
}
foreach($studentlehrverbaende[$sem_date] as $key=>$lehrverband)
$studlvbds = array_filter(
$studentlehrverbaende[$sem],
function($value) use ($sem_date) {
return $value->studiensemester_kurzbz === $sem_date;
}
);
foreach($studlvbds as $key=>$lehrverband)
{
$query .= "(((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 = ".$this->escape($lehrverband->gruppe)." AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).")";
// Eintraege fuer den ganzen Verband
+106
View File
@@ -56,5 +56,111 @@
}
}
/* min-width lets the flex item shrink, the fr row animates to the real content height.
without the row the collapsed panel keeps its height and blows up the row. */
#fhc-studiengang-info-column {
min-width: 0;
overflow: hidden;
display: grid;
grid-template-rows: 1fr;
transition: grid-template-rows 0.35s ease-in-out, opacity 0.35s ease-in-out, visibility 0s linear 0s;
}
/* the delay keeps the panel visible while it fades out, then takes it out of the tab order */
.studiengang-info-col.collapsed #fhc-studiengang-info-column {
grid-template-rows: 0fr;
opacity: 0;
visibility: hidden;
transition: grid-template-rows 0.35s ease-in-out, opacity 0.35s ease-in-out, visibility 0s linear 0.35s;
}
.studiengang-info-body {
min-height: 0;
overflow: hidden;
padding-top: 0.5rem;
}
.studiengang-info-title {
font-size: 0.875rem;
font-weight: 600;
line-height: 1.25;
margin-bottom: 0.25rem;
}
/* the rail stays visible when the panel is collapsed and names what it opens */
#studiengang-info-toggle {
cursor: pointer;
color: inherit;
align-items: center;
background-color: var(--fhc-secondary);
border: 1px solid var(--fhc-border);
border-radius: var(--bs-border-radius);
transition: width 0.35s ease-in-out, background-color 0.2s ease-in-out;
}
#studiengang-info-toggle:hover {
background-color: var(--fhc-secondary-highlight);
}
#studiengang-info-toggle .fa-chevron-right {
transition: all 0.5s ease-in-out;
}
.studiengang-info-col.collapsed #studiengang-info-toggle .fa-chevron-right {
transform: scaleX(-1);
color: var(--fhc-black-40);
}
/* the desktop view slides the column, same duration as the bootstrap collapse of the menu */
@media (min-width: 768px) {
.studiengang-info-col {
flex: 0 0 auto;
width: 25%;
transition: width 0.35s ease-in-out;
}
/* wide enough for the heading, the collapsed panel adds nothing */
.studiengang-info-col.collapsed {
width: 9.5rem;
}
/* the collapsed rail fills the column, the open one is a narrow strip beside the panel */
.studiengang-info-col.collapsed #studiengang-info-toggle {
width: 100%;
}
/* the strip can get very tall, so the chevron stays at the top where the heading is */
#studiengang-info-toggle {
align-items: flex-start;
}
/* the heading must not rewrap while the column slides, a wider font ellipsizes instead of overflowing */
.studiengang-info-title {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* only the narrow collapsed column breaks the heading into two lines */
.studiengang-info-col.collapsed .studiengang-info-title span {
display: block;
overflow: hidden;
text-overflow: ellipsis;
}
.studiengang-info-body {
padding-left: 1rem;
}
}
/* the mobile view stacks the block, so the chevron points up and down */
@media (max-width: 767px) {
#studiengang-info-toggle .fa-chevron-right {
transform: rotate(-90deg);
}
.studiengang-info-col.collapsed #studiengang-info-toggle .fa-chevron-right {
transform: rotate(90deg);
}
}
+13
View File
@@ -62,3 +62,16 @@
top:13%;"
z-index: 104; font-size: 1rem; width: 2.5rem; height: 2.5rem; opacity:0; transition: opacity 0.2s; top:13%;"
}*/
.tag-hover:hover {
background-color: #e9ecef;
}
.green {
background-color: #e9ecef;
}
.btn-hover {
--bs-btn-hover-bg: #e9ecef; /* Neue Hintergrundfarbe beim Hover */
--bs-btn-hover-border-color: #e9ecef; /* Neue Rahmenfarbe beim Hover */
}
+5
View File
@@ -145,3 +145,8 @@
float: right;
margin-top: 3px;
}
.btn-hover {
--bs-btn-hover-bg: #e9ecef;
--bs-btn-hover-border-color: #e9ecef;
}
+3 -2
View File
@@ -16,10 +16,11 @@
*/
export default {
studiengangInformation() {
studiengangInformation(studiengang_kz, semester) {
return {
method: 'get',
url: '/api/frontend/v1/Studgang/getStudiengangInfo'
url: '/api/frontend/v1/Studgang/getStudiengangInfo',
params: { studiengang_kz, semester }
};
},
getStudiengangByKz(studiengang_kz) {
+3
View File
@@ -174,6 +174,9 @@ export default {
>
{{ $p.t('lehre/noLvFound') }}
</div>
<div v-else-if="!renderers || !renderers[event.type]" class="placeholder-glow">
<span class="placeholder col-12"></span>
</div>
<div
v-else
:class="'event-type-' + event.type + ' ' + mode + 'PageContainer'"
+3
View File
@@ -79,6 +79,9 @@ export default {
>
{{ $p.t('lehre/noLvFound') }}
</div>
<div v-else-if="!renderers || !renderers[event.type]" class="placeholder-glow">
<span class="placeholder col-12"></span>
</div>
<component
v-else-if="mode == 'eventheader'"
:is="renderers[event.type]?.modalTitle"
@@ -7,7 +7,7 @@ export default {
data(){
return{
studiengang:null,
semester: null,
stg_semester: null,
stg_ltg: null,
gf_ltg: null,
stv_ltg: null,
@@ -21,7 +21,15 @@ props:{
displayWidget:{
type:Boolean,
default:false,
}
},
// without studiengang_kz the Studiengang of the logged in Student is loaded
studiengang_kz:[String, Number],
semester:[String, Number],
// compact drops the Studiengang header and the photos, so the block fits a narrow column
compact:{
type:Boolean,
default:false,
},
},
components:{
StudiengangPerson,
@@ -29,7 +37,7 @@ components:{
},
template:/*html*/`
<div id="fhc-studiengang-informationen">
<template v-if="studiengang?.bezeichnung && semester">
<template v-if="studiengang?.bezeichnung && !compact">
<div class="card card-body mb-3 border-0">
<div class="mb-1">
<h2 class="h4 mb-1 pb-0">{{$p.t('lehre','studiengang')}}:</h2>
@@ -39,17 +47,22 @@ template:/*html*/`
<h2 class="h4 mb-1 pb-0">Moodle:</h2>
<a class="fhc-link-color mb-1" target="_blank" :href="moodleLink">{{studiengang?.kurzbzlang}}</a>
</div>
<div :class="{'mb-1':studiengang?.zusatzinfo_html}">
<div :class="{'mb-1':studiengang?.zusatzinfo_html}" v-if="stg_semester">
<h2 class="h4 mb-1 pb-0">{{$p.t('lehre','studiensemester')}}: </h2>
<span class="mb-1">{{semester}}</span>
<span class="mb-1">{{stg_semester}}</span>
</div>
<div class="zusatzinfo" v-if="studiengang?.zusatzinfo_html" v-html="studiengang?.zusatzinfo_html"></div>
</div>
</template>
<template v-for="{title, collection} in collection_array">
<template v-if="Array.isArray(collection) && collection.length !==0">
<h2 class="h5 text-truncate">{{title}}</h2>
<template v-if="displayWidget">
<h2 :class="compact ? 'h6 mb-1 text-break' : 'h5 text-truncate'">{{title}}</h2>
<template v-if="compact">
<template v-for="person in collection">
<studiengang-person compact v-bind="person"></studiengang-person>
</template>
</template>
<template v-else-if="displayWidget">
<div class="d-flex flex-wrap flex-row mb-3 gap-2">
<template v-for="person in collection">
<studiengang-person displayWidget v-bind="person"></studiengang-person>
@@ -66,13 +79,13 @@ template:/*html*/`
</template>
</template>
<template v-if="hochschulvertr && Array.isArray(hochschulvertr) && hochschulvertr.length >0">
<studiengang-vertretung showBezeichnung :title="$p.t('studiengangInformation', 'Hochschulvertretung')" :vertretungsList="hochschulvertr"></studiengang-vertretung>
<studiengang-vertretung showBezeichnung :compact="compact" :title="$p.t('studiengangInformation', 'Hochschulvertretung')" :vertretungsList="hochschulvertr"></studiengang-vertretung>
</template>
<template v-if="stdv && Array.isArray(stdv) && stdv.length >0">
<studiengang-vertretung :title="$p.t('studiengangInformation', 'Studienvertretung').concat(studiengang?.kurzbzlang??'')" :vertretungsList="stdv"></studiengang-vertretung>
<studiengang-vertretung :compact="compact" :title="$p.t('studiengangInformation', 'Studienvertretung').concat(' ' + studiengang?.kurzbzlang??'')" :vertretungsList="stdv"></studiengang-vertretung>
</template>
<template v-if="jahrgangsvertr && Array.isArray(jahrgangsvertr) && jahrgangsvertr.length >0">
<studiengang-vertretung :title="$p.t('studiengangInformation', 'Jahrgangsvertretung')" :vertretungsList="jahrgangsvertr"></studiengang-vertretung>
<studiengang-vertretung :compact="compact" :title="$p.t('studiengangInformation', 'Jahrgangsvertretung')" :vertretungsList="jahrgangsvertr"></studiengang-vertretung>
</template>
</div>
@@ -104,6 +117,9 @@ computed:{
return returnData;
},
infoParameter: function(){
return [this.studiengang_kz, this.semester].join('-');
},
moodleLink: function(){
// early return if the studiengang information is not available
if(!this.studiengang || !this.studiengang.studiengang_kz) return;
@@ -111,12 +127,25 @@ computed:{
return `https://moodle.technikum-wien.at/course/view.php?idnumber=dl` + this.studiengang.studiengang_kz;
},
},
mounted() {
methods:{
loadStudiengangInformation: function(){
this.$api
.call(ApiStudiengang.studiengangInformation())
.call(ApiStudiengang.studiengangInformation(this.studiengang_kz, this.semester))
.then(res => res.data)
.then(studiengangInformationen => {
Object.assign(this, studiengangInformationen);
const { semester, ...rest } = studiengangInformationen ?? {};
this.stg_semester = semester ?? null;
Object.assign(this, rest);
});
}
},
},
watch:{
// one watcher for both parameters prevents duplicate requests
infoParameter: function(){
this.loadStudiengangInformation();
},
},
mounted() {
this.loadStudiengangInformation();
}
};
@@ -12,10 +12,32 @@ export default {
displayWidget:{
type:Boolean,
default:false,
},
// compact drops the photo and the card chrome, like the old CIS teambox
compact:{
type:Boolean,
default:false,
}
},
template:/*html*/`
<div class="card border-0" :style="{'width':displayWidget?'12rem':'15rem'}">
<div v-if="compact" class="mb-2">
<div class="fw-semibold">{{fullname}} <a v-if="profilViewLink" :href="profilViewLink" :aria-label="$p.t('profil','profil')" :title="$p.t('profil','profil')"><i class="ms-1 fa fa-arrow-up-right-from-square fhc-primary-color" aria-hidden="true"></i></a></div>
<dl class="stgkontaktinfo mb-0">
<template v-if="phone">
<dt><i class="fa fa-phone me-2"></i></dt>
<dd class="mb-0"><a class="fhc-link-color" :href="phone.link">{{phone.number}}</a></dd>
</template>
<template v-if="ort">
<dt><i class="fa fa-home me-2"></i></dt>
<dd class="mb-0">{{ort}}</dd>
</template>
<template v-if="email">
<dt><i class="fa-regular fa-envelope me-2"></i></dt>
<dd class="mb-0"><a class="fhc-link-color" :href="email_link" v-html="formattedEmail"></a></dd>
</template>
</dl>
</div>
<div v-else class="card border-0" :style="{'width':displayWidget?'12rem':'15rem'}">
<div class="d-flex justify-content-center">
<img :src="base64Image" alt="mitarbeiter_foto" style="width: 110px; height: auto; object-fir:scale-down;" class="card-img-top" >
</div>
@@ -3,14 +3,18 @@ export default {
title:String,
vertretungsList:Array,
showBezeichnung:Boolean,
compact:{
type:Boolean,
default:false,
},
},
template:/*html*/`
<div class="card mb-3 border-0">
<div class="card-header">
<span>{{title}}</span>
<div :class="compact ? 'mb-2' : 'card mb-3 border-0'">
<div :class="compact ? '' : 'card-header'">
<span :class="compact ? 'fw-semibold' : ''">{{title}}</span>
</div>
<div class="card-body">
<p v-for="vertretung in vertretungsList">
<div :class="compact ? '' : 'card-body'">
<p v-for="vertretung in vertretungsList" :class="compact ? 'mb-0' : ''">
<a v-if="profilViewLink(vertretung.uid)" :href="profilViewLink(vertretung.uid)" :aria-label="$p.t('profil','profil')" :title="$p.t('profil','profil')">
<i class="me-2 fa fa-arrow-up-right-from-square fhc-primary-color" aria-hidden="true"></i>
</a>
+123 -89
View File
@@ -1,4 +1,5 @@
import LvUebersicht from "../Mylv/LvUebersicht.js";
import StudiengangInformation from "../Cms/StudiengangInformation/StudiengangInformation.js";
import ApiCisStudium from '../../../api/factory/cis/studium.js';
@@ -16,6 +17,7 @@ export default {
lehrveranstaltungen: [],
selectedLehrveranstaltung: null,
menu:null,
showStudiengangInfo: false,
}
},
provide(){
@@ -28,8 +30,10 @@ export default {
}
},
name: "OverviewStudiengaenge",
inject: ["isMobile"],
components: {
LvUebersicht,
StudiengangInformation,
},
watch:{
selectedStudiensemester: function(newVal, oldVal){
@@ -119,6 +123,10 @@ export default {
const value = localStorage.getItem(key);
return value;
},
toggleStudiengangInfo(){
this.showStudiengangInfo = !this.showStudiengangInfo;
this.storeDataToLocalStorage("studiengangInfo", this.showStudiengangInfo);
},
changeSelectedStudienSemester(studiensemester_kurzbz) {
return this.$api
.call(ApiCisStudium.getAllStudienSemester(studiensemester_kurzbz, this.selectedStudiengang, this.selectedSemester, this.selectedStudienordnung))
@@ -245,6 +253,11 @@ export default {
},
computed:{
studiengangInfoToggleTitel(){
return this.showStudiengangInfo
? this.$p.t('studiengangInformation', 'studiengangsinformationen_ausblenden')
: this.$p.t('studiengangInformation', 'studiengangsinformationen_anzeigen');
},
isGermanLanguage(){
return this.$p.user_language.value == "German"
},
@@ -285,6 +298,10 @@ export default {
created(){
// the last toggle wins, otherwise the desktop view shows the information and the mobile view hides it
const studiengangInfo = this.getDataFromLocalStorage("studiengangInfo");
this.showStudiengangInfo = studiengangInfo === null ? !this.isMobile : studiengangInfo === "true";
const studiensemester = this.getDataFromLocalStorage("sudiensemester") ?? undefined;
const studiengang = JSON.parse(this.getDataFromLocalStorage("studiengang")) ?? undefined;
const semester = this.getDataFromLocalStorage("semester") ?? undefined;
@@ -302,102 +319,119 @@ export default {
},
template: /*html*/`
<div>
<h2>{{$p.t('studium','studium')}}</h2>
<hr>
<lv-uebersicht ref="lvUebersicht" :titel="selectedLehrveranstaltungTitel" :event="selectedLehrveranstaltung" :studiensemester="selectedStudiensemester" v-if="selectedLehrveranstaltung">
<template #content>
<div v-if="Array.isArray(selectedLehrveranstaltung.lektoren) && selectedLehrveranstaltung.lektoren.length>0" class="mb-4">
<h4>{{$p.t('studium','lektoren')}}:</h4>
<a :href="'mailto:'+lektor?.email" class="fhc-link-color mx-2" v-for="lektor in selectedLehrveranstaltung.lektoren">{{lektor.name}}</a>
<h2>{{$p.t('studium','studium')}}</h2>
<hr>
<lv-uebersicht ref="lvUebersicht" :titel="selectedLehrveranstaltungTitel" :event="selectedLehrveranstaltung" :studiensemester="selectedStudiensemester" v-if="selectedLehrveranstaltung">
<template #content>
<div v-if="Array.isArray(selectedLehrveranstaltung.lektoren) && selectedLehrveranstaltung.lektoren.length>0" class="mb-4">
<h4>{{$p.t('studium','lektoren')}}:</h4>
<a :href="'mailto:'+lektor?.email" class="fhc-link-color mx-2" v-for="lektor in selectedLehrveranstaltung.lektoren">{{lektor.name}}</a>
</div>
<h4>Menu:</h4>
</template>
</lv-uebersicht>
<div class="lvOptions">
<div>
<h6>{{$p.t('studium','studiensemester')}}:</h6>
<div class="input-group">
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeStudiensemester(1)" :aria-label="$p.t('global','previous')" :title="$p.t('global','previous')">
<i class="fa fa-caret-left" aria-hidden="true"></i>
</button>
<select ref="studiensemester" v-model="selectedStudiensemester" @change="onStudiensemesterChange" class="form-select" :aria-label="$p.t('global/studiensemester_auswaehlen')">
<option v-for="semester in studienSemester" :key="semester" :value="semester.studiensemester_kurzbz">{{studiensemesterTitel(semester.studiensemester_kurzbz) }}</option>
</select>
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeStudiensemester(-1)" :aria-label="$p.t('global','next')" :title="$p.t('global','next')">
<i class="fa fa-caret-right" aria-hidden="true"></i>
</button>
</div>
</div>
<h4>Menu:</h4>
</template>
</lv-uebersicht>
<div class="lvOptions">
<div>
<h6>{{$p.t('studium','studiensemester')}}:</h6>
<div class="input-group">
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeStudiensemester(1)" :aria-label="$p.t('global','previous')" :title="$p.t('global','previous')">
<i class="fa fa-caret-left" aria-hidden="true"></i>
</button>
<select ref="studiensemester" v-model="selectedStudiensemester" @change="onStudiensemesterChange" class="form-select" :aria-label="$p.t('global/studiensemester_auswaehlen')">
<option v-for="semester in studienSemester" :key="semester" :value="semester.studiensemester_kurzbz">{{studiensemesterTitel(semester.studiensemester_kurzbz) }}</option>
</select>
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeStudiensemester(-1)" :aria-label="$p.t('global','next')" :title="$p.t('global','next')">
<i class="fa fa-caret-right" aria-hidden="true"></i>
</button>
</div>
</div>
<div>
<h6>{{$p.t('lehre','studiengang')}}:</h6>
<div class="input-group">
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeStudiengang(-1)" :aria-label="$p.t('global','previous')" :title="$p.t('global','previous')">
<i class="fa fa-caret-left" aria-hidden="true"></i>
</button>
<select ref="studiengaenge" v-model="selectedStudiengang" class="form-select" @change="onStudiengangChange" :aria-label="$p.t('global/studiensemester_auswaehlen')">
<option v-for="studiengang in studiengaenge" :key="studiengang.studiengang_kz" :value="studiengang.studiengang_kz" >{{studiengangTitel(studiengang)}}</option>
</select>
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeStudiengang(1)" :aria-label="$p.t('global','next')" :title="$p.t('global','next')">
<i class="fa fa-caret-right" aria-hidden="true"></i>
</button>
</div>
</div>
<div>
<h6>{{$p.t('lehre','semester')}}:</h6>
<div class="input-group">
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeSemester(-1)" :aria-label="$p.t('global','previous')" :title="$p.t('global','previous')">
<i class="fa fa-caret-left" aria-hidden="true"></i>
</button>
<select ref="semester" v-model="selectedSemester" class="form-select" @change="onSemesterChange" :aria-label="$p.t('global/studiensemester_auswaehlen')">
<option v-for="sem in semester" :key="sem" :value="sem">{{sem}}. Semester</option>
</select>
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeSemester(1)" :aria-label="$p.t('global','next')" :title="$p.t('global','next')">
<i class="fa fa-caret-right" aria-hidden="true"></i>
</button>
</div>
</div>
<div>
<h6>{{$p.t('studium','studienordnung')}}:</h6>
<div class="input-group">
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeStudienordnung(-1)" :aria-label="$p.t('global','previous')" :title="$p.t('global','previous')">
<i class="fa fa-caret-left" aria-hidden="true"></i>
</button>
<select ref="studienordnung" v-model="selectedStudienordnung" class="form-select" @change="onStudienordnungChange" :aria-label="$p.t('global/studiensemester_auswaehlen')">
<option v-for="ordnung in computedStudienOrdnungSelectValues" :disabled="ordnung.disabled" :key="ordnung?.studienplan?.studienplan_id" :value="ordnung?.studienplan?.studienplan_id">{{ordnung.bezeichnung}}</option>
</select>
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeStudienordnung(1)" :aria-label="$p.t('global','next')" :title="$p.t('global','next')">
<i class="fa fa-caret-right" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
<hr>
<div class="lvUebersicht " >
<template v-for="lehrveranstaltung in lehrveranstaltungen" :key="lehrveranstaltung.lehrveranstaltung_id">
<div class="card" v-if="Array.isArray(lehrveranstaltung.lehrveranstaltungen) && lehrveranstaltung.lehrveranstaltungen.length >0" >
<div class="card-header">
<h5 class=" card-title">{{isGermanLanguage ? lehrveranstaltung.bezeichnung : lehrveranstaltung.bezeichnung_english }}</h5>
<h6 class=" card-subtitle">{{lehrveranstaltung.lehrform_kurzbz}}</h6>
<div>
<h6>{{$p.t('lehre','studiengang')}}:</h6>
<div class="input-group">
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeStudiengang(-1)" :aria-label="$p.t('global','previous')" :title="$p.t('global','previous')">
<i class="fa fa-caret-left" aria-hidden="true"></i>
</button>
<select ref="studiengaenge" v-model="selectedStudiengang" class="form-select" @change="onStudiengangChange" :aria-label="$p.t('global/studiensemester_auswaehlen')">
<option v-for="studiengang in studiengaenge" :key="studiengang.studiengang_kz" :value="studiengang.studiengang_kz" >{{studiengangTitel(studiengang)}}</option>
</select>
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeStudiengang(1)" :aria-label="$p.t('global','next')" :title="$p.t('global','next')">
<i class="fa fa-caret-right" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="card-body">
<ul class="list-group list-group-flush">
<li class="d-flex list-group-item" v-for="lv in lehrveranstaltung.lehrveranstaltungen">
<a class="fhc-link-color d-block me-auto" href="#" @click="openLvUebersicht(lv)">{{isGermanLanguage ? lv.bezeichnung : lv.bezeichnung_english}}</a>
<p>{{lv.lehrform_kurzbz}}</p>
</li>
</ul>
<div>
<h6>{{$p.t('lehre','semester')}}:</h6>
<div class="input-group">
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeSemester(-1)" :aria-label="$p.t('global','previous')" :title="$p.t('global','previous')">
<i class="fa fa-caret-left" aria-hidden="true"></i>
</button>
<select ref="semester" v-model="selectedSemester" class="form-select" @change="onSemesterChange" :aria-label="$p.t('global/studiensemester_auswaehlen')">
<option v-for="sem in semester" :key="sem" :value="sem">{{sem}}. Semester</option>
</select>
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeSemester(1)" :aria-label="$p.t('global','next')" :title="$p.t('global','next')">
<i class="fa fa-caret-right" aria-hidden="true"></i>
</button>
</div>
</div>
<div>
<h6>{{$p.t('studium','studienordnung')}}:</h6>
<div class="input-group">
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeStudienordnung(-1)" :aria-label="$p.t('global','previous')" :title="$p.t('global','previous')">
<i class="fa fa-caret-left" aria-hidden="true"></i>
</button>
<select ref="studienordnung" v-model="selectedStudienordnung" class="form-select" @change="onStudienordnungChange" :aria-label="$p.t('global/studiensemester_auswaehlen')">
<option v-for="ordnung in computedStudienOrdnungSelectValues" :disabled="ordnung.disabled" :key="ordnung?.studienplan?.studienplan_id" :value="ordnung?.studienplan?.studienplan_id">{{ordnung.bezeichnung}}</option>
</select>
<button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeStudienordnung(1)" :aria-label="$p.t('global','next')" :title="$p.t('global','next')">
<i class="fa fa-caret-right" aria-hidden="true"></i>
</button>
</div>
</div>
</div>
</template>
</div>
<hr>
<div class="row g-3">
<div class="col-12 order-last studiengang-info-col" :class="{collapsed: !showStudiengangInfo}" v-if="selectedStudiengang">
<h2 class="studiengang-info-title"><span>{{$p.t('global','ansprechpartner')}}</span> <span>{{$p.t('lehre','studiengang')}}</span></h2>
<div class="d-flex flex-column flex-md-row">
<button id="studiengang-info-toggle" type="button" class="d-flex justify-content-center p-2 flex-shrink-0"
@click="toggleStudiengangInfo"
:aria-label="studiengangInfoToggleTitel" :title="studiengangInfoToggleTitel"
:aria-expanded="showStudiengangInfo" aria-controls="fhc-studiengang-info-column">
<i aria-hidden="true" class="fa-solid fa-chevron-right fhc-text"></i>
</button>
<div id="fhc-studiengang-info-column" class="flex-grow-1">
<div class="studiengang-info-body">
<studiengang-information compact :studiengang_kz="selectedStudiengang" :semester="selectedSemester"></studiengang-information>
</div>
</div>
</div>
</div>
<div class="col-12 col-md">
<div class="lvUebersicht " >
<template v-for="lehrveranstaltung in lehrveranstaltungen" :key="lehrveranstaltung.lehrveranstaltung_id">
<div class="card" v-if="Array.isArray(lehrveranstaltung.lehrveranstaltungen) && lehrveranstaltung.lehrveranstaltungen.length >0" >
<div class="card-header">
<h5 class=" card-title">{{isGermanLanguage ? lehrveranstaltung.bezeichnung : lehrveranstaltung.bezeichnung_english }}</h5>
<h6 class=" card-subtitle">{{lehrveranstaltung.lehrform_kurzbz}}</h6>
</div>
<div class="card-body">
<ul class="list-group list-group-flush">
<li class="d-flex list-group-item" v-for="lv in lehrveranstaltung.lehrveranstaltungen">
<a class="fhc-link-color d-block me-auto" href="#" @click="openLvUebersicht(lv)">{{isGermanLanguage ? lv.bezeichnung : lv.bezeichnung_english}}</a>
<p>{{lv.lehrform_kurzbz}}</p>
</li>
</ul>
</div>
</div>
</template>
</div>
</div>
</div>
</div>
`
};
@@ -400,32 +400,37 @@ export default {
<div v-if="headerData.length == 1">
<div v-if="!isLoading" class="d-flex align-items-center gap-3">
<h2 class="h4">
<h2 class="h4 mt-2">
{{headerData[0].titelpre}}
{{headerData[0].vorname}}
{{headerData[0].nachname}}
<span v-if="headerData[0].titelpost">, </span>
{{headerData[0].titelpost}}
</h2>
<core-tag ref="tagComponent"
v-if="tagsEnabled"
:endpoint="tagEndpoint"
:values="prestudentIds"
@added="addedTag"
@deleted="deletedTag"
@updated="updatedTag"
zuordnung_typ="prestudent_id"
></core-tag>
<div
role="button"
v-if="tagsEnabled"
@click="rebuildPrestudentTags"
class="btn btn-outline btn-light mb-1"
:title="'Automatische Tags fuer ' + currentSemester + ' neu laden'"
>
<i class="fa-solid fa-refresh pe-1"></i>
<span>{{currentSemester}}</span>
<div class="d-flex border rounded align-items-center ps-1">
<core-tag ref="tagComponent"
v-if="tagsEnabled"
:endpoint="tagEndpoint"
:values="prestudentIds"
:show-hover="true"
@added="addedTag"
@deleted="deletedTag"
@updated="updatedTag"
zuordnung_typ="prestudent_id"
></core-tag>
<div
role="button"
v-if="tagsEnabled"
@click="rebuildPrestudentTags"
class="btn btn-outline btn-sm btn-hover m-1"
:title="$p.t('tag','rebuild_tags') + ' ' + currentSemester"
>
<i class="fa-solid fa-refresh pe-1"></i>
<span>{{currentSemester}}</span>
</div>
</div>
<h6 v-if="headerData[0].unruly" class="badge" :class="'bg-unruly rounded-0'"><strong>unruly</strong></h6>
</div>
<div v-else class="d-flex align-items-center gap-3">
@@ -553,8 +553,12 @@ export default {
}
if (!this.formData.akadgrad_id && this.arrAkadGrad.length > 0) {
if(this.student.geschlecht == 'w')
this.formData.akadgrad_id = this.arrAkadGrad[1].akadgrad_id;
const akadGradByGeschlecht = this.arrAkadGrad.find((item) => {
return item.geschlecht === this.student.geschlecht;
});
if(akadGradByGeschlecht)
this.formData.akadgrad_id = akadGradByGeschlecht.akadgrad_id;
else
this.formData.akadgrad_id = this.arrAkadGrad[0].akadgrad_id;
}
@@ -317,6 +317,7 @@ export default {
"$p.user_language.value"(n, o) {
if (n !== o && o !== undefined && this.$refs.table.tableBuilt) {
this.translateTabulator();
this.$reloadList();
}
},
"tagFilterState.selectedOptions": {
@@ -842,35 +843,39 @@ export default {
</div>
</template>
<template #actions>
<core-tag ref="tagComponent"
v-if="tagsEnabled"
:endpoint="tagEndpoint"
:values="selectedColumnValues"
@added="addedTag"
@deleted="deletedTag"
@updated="updatedTag"
zuordnung_typ="prestudent_id"
></core-tag>
<template #tags>
<div class="d-flex border rounded align-items-center ps-1">
<core-tag ref="tagComponent"
v-if="tagsEnabled"
:endpoint="tagEndpoint"
:values="selectedColumnValues"
@added="addedTag"
@deleted="deletedTag"
@updated="updatedTag"
zuordnung_typ="prestudent_id"
show-hover
></core-tag>
<button
v-if="!selected.length"
class="btn btn-outline btn-light mb-1"
@click="rebuild(selected)"
:title="$p.t('tag','rebuild_tags') + ' Stg ' + currentSemester"
>
<i class="fa-solid fa-refresh pe-1"></i> STG
</button>
<button
v-else
class="btn btn-outline btn-light mb-1"
@click="rebuild(selected)"
:title="$p.t('tag','rebuild_tags') + ' ' + $p.t('ui','selection') + ' ' + currentSemester"
>
<i class="fa-solid fa-refresh pe-1"></i> {{selected.length}}
</button>
<button
v-if="!selected.length"
class="btn btn-outline btn-sm m-1 btn-hover"
@click="rebuild(selected)"
:title="$p.t('tag','rebuild_tags') + ' Stg ' + currentSemester"
>
<i class="fa-solid fa-refresh pe-1"></i> STG
</button>
<button
v-else
class="btn btn-outline btn-sm m-1 btn-hover"
@click="rebuild(selected)"
:title="$p.t('tag','rebuild_tags') + ' ' + $p.t('ui','selection') + ' ' + currentSemester"
>
<i class="fa-solid fa-refresh pe-1"></i> {{selected.length}}
</button>
</div>
</template>
<template v-if="filter.length || headerFilterActive">
<template v-if="filter.length || headerFilterActive">
<div class="d-flex justify-content-center align-items-center gap-2 ps-4 position-absolute start-50 translate-middle-x">
<p class="text-danger mb-0">
<strong>{{$p.t('filter','filterActive')}}</strong>
@@ -884,8 +889,6 @@ export default {
<span class="fa-solid fa-filter-circle-xmark"></span>
</button>
</div>
</template>
</template>
<template #filter>
@@ -895,6 +898,7 @@ export default {
</div>
</div>
</template>
</core-filter-cmpt>
</div>
<list-new ref="new" :studiengang-kz="studiengangKz" :studiensemester-kurzbz="studiensemesterKurzbz"></list-new>
+6 -1
View File
@@ -28,6 +28,10 @@ export default {
confirmLimit: {
type: Number,
default: 20
},
showHover: {
type: Boolean,
default: false
}
},
data() {
@@ -228,7 +232,8 @@ export default {
<span :title="values.length === 0 ? 'Bitte Zeilen markieren' : ''">
<button @mouseover="showList = true"
:disabled="!values || values.length === 0"
class="btn btn-sm">
class="btn btn-sm"
:class="{'btn-hover': showHover}">
<i class="fa-solid fa-tag fa-xl"></i>
</button>
</span>
+2 -1
View File
@@ -1094,7 +1094,7 @@ export const CoreFilterCmpt = {
<div :id="'filterCollapsables' + idExtra">
<div class="d-flex flex-row justify-content-between flex-wrap">
<div v-if="newBtnShow || reload || $slots.search || $slots.actions" class="d-flex gap-2 align-items-baseline flex-wrap">
<div v-if="newBtnShow || reload || $slots.search || $slots.actions || $slots.tags" class="d-flex gap-2 align-items-baseline flex-wrap">
<button v-if="newBtnShow" class="btn btn-primary" :class="newBtnClass" :title="newBtnLabel ? undefined : 'New'" :aria-label="newBtnLabel ? undefined : 'New'" @click="$emit('click:new', $event)" :disabled="newBtnDisabled">
<span class="fa-solid fa-plus" aria-hidden="true"></span>
{{ newBtnLabel }}
@@ -1107,6 +1107,7 @@ export const CoreFilterCmpt = {
<span v-else id="selected-info-text"> Mit {{ selectedData.length }} ausgewählten:</span>
</span>
<slot name="actions" v-bind="{selected: tabulatorHasSelector ? selectedData : []}"></slot>
<slot name="tags"></slot>
<slot name="search"></slot>
</div>
<div class="d-flex gap-1 align-items-baseline flex-grow-1 justify-content-end">
+40
View File
@@ -49059,6 +49059,46 @@ array(
)
)
),
array(
'app' => 'core',
'category' => 'studiengangInformation',
'phrase' => 'studiengangsinformationen_anzeigen',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Studiengangsinformationen einblenden",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Show degree program information",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'studiengangInformation',
'phrase' => 'studiengangsinformationen_ausblenden',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Studiengangsinformationen ausblenden",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Hide degree program information",
'description' => '',
'insertvon' => 'system'
)
)
),
// ### STUDIENGANG_INFORMATIONEN PHRASEN ENDE
array(
'app' => 'core',