Compare commits

...
9 changed files with 393 additions and 131 deletions
@@ -44,14 +44,29 @@ class Studgang extends FHCAPI_Controller
// Public methods // Public methods
public function getStudiengangInfo(){ public function getStudiengangInfo(){
$isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID()); $studiengang_kz = $this->input->get('studiengang_kz', true);
$isMitarbeiter = $this->getDataOrTerminateWithError($isMitarbeiter); $semester = $this->input->get('semester', true);
if($isMitarbeiter) {
$this->terminateWithSuccess(null); // 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 // 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); $studiengangInfo= $this->getDataOrTerminateWithError($studiengangInfo);
$this->terminateWithSuccess($studiengangInfo); $this->terminateWithSuccess($studiengangInfo);
} }
@@ -653,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 * @return stdClass
*/ */
public function getStudiengangInfoForNews() public function getStudiengangInfoForNews($studiengang_kz = null, $semester = null)
{ {
$this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel');
$this->load->model('person/Person_model', 'PersonModel'); $this->load->model('person/Person_model', 'PersonModel');
$this->load->model('crm/Student_model', 'StudentModel'); $this->load->model('crm/Student_model', 'StudentModel');
$student = $this->StudentModel->loadWhere(['student_uid' => getAuthUID()]); if (is_null($studiengang_kz))
if (isError($student)) {
return error($student); $student = $this->StudentModel->loadWhere(['student_uid' => getAuthUID()]);
if (getData($student)) { if (isError($student))
$student = current(getData($student)); return error($student);
$studiengang_kz = $student->studiengang_kz; if (getData($student)) {
$semester = $student->semester; $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); $stg_obj = $this->load($studiengang_kz);
if(isError($stg_obj)) if(isError($stg_obj))
return error($stg_obj); return error($stg_obj);
if(getData($stg_obj)) if(!hasData($stg_obj))
{ return error('Studiengang nicht gefunden');
$stg_obj = current(getData($stg_obj)); $stg_obj = current(getData($stg_obj));
}
$stg_ltg = $this->getLeitungDetailed($stg_obj->studiengang_kz); $stg_ltg = $this->getLeitungDetailed($stg_obj->studiengang_kz);
if (isError($stg_ltg)) if (isError($stg_ltg))
+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);
}
}
+3 -2
View File
@@ -16,10 +16,11 @@
*/ */
export default { export default {
studiengangInformation() { studiengangInformation(studiengang_kz, semester) {
return { return {
method: 'get', method: 'get',
url: '/api/frontend/v1/Studgang/getStudiengangInfo' url: '/api/frontend/v1/Studgang/getStudiengangInfo',
params: { studiengang_kz, semester }
}; };
}, },
getStudiengangByKz(studiengang_kz) { getStudiengangByKz(studiengang_kz) {
@@ -7,7 +7,7 @@ export default {
data(){ data(){
return{ return{
studiengang:null, studiengang:null,
semester: null, stg_semester: null,
stg_ltg: null, stg_ltg: null,
gf_ltg: null, gf_ltg: null,
stv_ltg: null, stv_ltg: null,
@@ -21,7 +21,15 @@ props:{
displayWidget:{ displayWidget:{
type:Boolean, type:Boolean,
default:false, 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:{ components:{
StudiengangPerson, StudiengangPerson,
@@ -29,7 +37,7 @@ components:{
}, },
template:/*html*/` template:/*html*/`
<div id="fhc-studiengang-informationen"> <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="card card-body mb-3 border-0">
<div class="mb-1"> <div class="mb-1">
<h2 class="h4 mb-1 pb-0">{{$p.t('lehre','studiengang')}}:</h2> <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> <h2 class="h4 mb-1 pb-0">Moodle:</h2>
<a class="fhc-link-color mb-1" target="_blank" :href="moodleLink">{{studiengang?.kurzbzlang}}</a> <a class="fhc-link-color mb-1" target="_blank" :href="moodleLink">{{studiengang?.kurzbzlang}}</a>
</div> </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> <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>
<div class="zusatzinfo" v-if="studiengang?.zusatzinfo_html" v-html="studiengang?.zusatzinfo_html"></div> <div class="zusatzinfo" v-if="studiengang?.zusatzinfo_html" v-html="studiengang?.zusatzinfo_html"></div>
</div> </div>
</template> </template>
<template v-for="{title, collection} in collection_array"> <template v-for="{title, collection} in collection_array">
<template v-if="Array.isArray(collection) && collection.length !==0"> <template v-if="Array.isArray(collection) && collection.length !==0">
<h2 class="h5 text-truncate">{{title}}</h2> <h2 :class="compact ? 'h6 mb-1 text-break' : 'h5 text-truncate'">{{title}}</h2>
<template v-if="displayWidget"> <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"> <div class="d-flex flex-wrap flex-row mb-3 gap-2">
<template v-for="person in collection"> <template v-for="person in collection">
<studiengang-person displayWidget v-bind="person"></studiengang-person> <studiengang-person displayWidget v-bind="person"></studiengang-person>
@@ -66,13 +79,13 @@ template:/*html*/`
</template> </template>
</template> </template>
<template v-if="hochschulvertr && Array.isArray(hochschulvertr) && hochschulvertr.length >0"> <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>
<template v-if="stdv && Array.isArray(stdv) && stdv.length >0"> <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>
<template v-if="jahrgangsvertr && Array.isArray(jahrgangsvertr) && jahrgangsvertr.length >0"> <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> </template>
</div> </div>
@@ -104,6 +117,9 @@ computed:{
return returnData; return returnData;
}, },
infoParameter: function(){
return [this.studiengang_kz, this.semester].join('-');
},
moodleLink: function(){ moodleLink: function(){
// early return if the studiengang information is not available // early return if the studiengang information is not available
if(!this.studiengang || !this.studiengang.studiengang_kz) return; 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; return `https://moodle.technikum-wien.at/course/view.php?idnumber=dl` + this.studiengang.studiengang_kz;
}, },
}, },
mounted() { methods:{
loadStudiengangInformation: function(){
this.$api this.$api
.call(ApiStudiengang.studiengangInformation()) .call(ApiStudiengang.studiengangInformation(this.studiengang_kz, this.semester))
.then(res => res.data) .then(res => res.data)
.then(studiengangInformationen => { .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:{ displayWidget:{
type:Boolean, type:Boolean,
default:false, default:false,
},
// compact drops the photo and the card chrome, like the old CIS teambox
compact:{
type:Boolean,
default:false,
} }
}, },
template:/*html*/` 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"> <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" > <img :src="base64Image" alt="mitarbeiter_foto" style="width: 110px; height: auto; object-fir:scale-down;" class="card-img-top" >
</div> </div>
@@ -3,14 +3,18 @@ export default {
title:String, title:String,
vertretungsList:Array, vertretungsList:Array,
showBezeichnung:Boolean, showBezeichnung:Boolean,
compact:{
type:Boolean,
default:false,
},
}, },
template:/*html*/` template:/*html*/`
<div class="card mb-3 border-0"> <div :class="compact ? 'mb-2' : 'card mb-3 border-0'">
<div class="card-header"> <div :class="compact ? '' : 'card-header'">
<span>{{title}}</span> <span :class="compact ? 'fw-semibold' : ''">{{title}}</span>
</div> </div>
<div class="card-body"> <div :class="compact ? '' : 'card-body'">
<p v-for="vertretung in vertretungsList"> <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')"> <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> <i class="me-2 fa fa-arrow-up-right-from-square fhc-primary-color" aria-hidden="true"></i>
</a> </a>
+123 -89
View File
@@ -1,4 +1,5 @@
import LvUebersicht from "../Mylv/LvUebersicht.js"; import LvUebersicht from "../Mylv/LvUebersicht.js";
import StudiengangInformation from "../Cms/StudiengangInformation/StudiengangInformation.js";
import ApiCisStudium from '../../../api/factory/cis/studium.js'; import ApiCisStudium from '../../../api/factory/cis/studium.js';
@@ -16,6 +17,7 @@ export default {
lehrveranstaltungen: [], lehrveranstaltungen: [],
selectedLehrveranstaltung: null, selectedLehrveranstaltung: null,
menu:null, menu:null,
showStudiengangInfo: false,
} }
}, },
provide(){ provide(){
@@ -28,8 +30,10 @@ export default {
} }
}, },
name: "OverviewStudiengaenge", name: "OverviewStudiengaenge",
inject: ["isMobile"],
components: { components: {
LvUebersicht, LvUebersicht,
StudiengangInformation,
}, },
watch:{ watch:{
selectedStudiensemester: function(newVal, oldVal){ selectedStudiensemester: function(newVal, oldVal){
@@ -119,6 +123,10 @@ export default {
const value = localStorage.getItem(key); const value = localStorage.getItem(key);
return value; return value;
}, },
toggleStudiengangInfo(){
this.showStudiengangInfo = !this.showStudiengangInfo;
this.storeDataToLocalStorage("studiengangInfo", this.showStudiengangInfo);
},
changeSelectedStudienSemester(studiensemester_kurzbz) { changeSelectedStudienSemester(studiensemester_kurzbz) {
return this.$api return this.$api
.call(ApiCisStudium.getAllStudienSemester(studiensemester_kurzbz, this.selectedStudiengang, this.selectedSemester, this.selectedStudienordnung)) .call(ApiCisStudium.getAllStudienSemester(studiensemester_kurzbz, this.selectedStudiengang, this.selectedSemester, this.selectedStudienordnung))
@@ -245,6 +253,11 @@ export default {
}, },
computed:{ computed:{
studiengangInfoToggleTitel(){
return this.showStudiengangInfo
? this.$p.t('studiengangInformation', 'studiengangsinformationen_ausblenden')
: this.$p.t('studiengangInformation', 'studiengangsinformationen_anzeigen');
},
isGermanLanguage(){ isGermanLanguage(){
return this.$p.user_language.value == "German" return this.$p.user_language.value == "German"
}, },
@@ -285,6 +298,10 @@ export default {
created(){ 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 studiensemester = this.getDataFromLocalStorage("sudiensemester") ?? undefined;
const studiengang = JSON.parse(this.getDataFromLocalStorage("studiengang")) ?? undefined; const studiengang = JSON.parse(this.getDataFromLocalStorage("studiengang")) ?? undefined;
const semester = this.getDataFromLocalStorage("semester") ?? undefined; const semester = this.getDataFromLocalStorage("semester") ?? undefined;
@@ -302,102 +319,119 @@ export default {
}, },
template: /*html*/` template: /*html*/`
<div> <div>
<h2>{{$p.t('studium','studium')}}</h2> <h2>{{$p.t('studium','studium')}}</h2>
<hr> <hr>
<lv-uebersicht ref="lvUebersicht" :titel="selectedLehrveranstaltungTitel" :event="selectedLehrveranstaltung" :studiensemester="selectedStudiensemester" v-if="selectedLehrveranstaltung"> <lv-uebersicht ref="lvUebersicht" :titel="selectedLehrveranstaltungTitel" :event="selectedLehrveranstaltung" :studiensemester="selectedStudiensemester" v-if="selectedLehrveranstaltung">
<template #content> <template #content>
<div v-if="Array.isArray(selectedLehrveranstaltung.lektoren) && selectedLehrveranstaltung.lektoren.length>0" class="mb-4"> <div v-if="Array.isArray(selectedLehrveranstaltung.lektoren) && selectedLehrveranstaltung.lektoren.length>0" class="mb-4">
<h4>{{$p.t('studium','lektoren')}}:</h4> <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> <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> </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> <div>
<h6>{{$p.t('lehre','studiengang')}}:</h6> <h6>{{$p.t('lehre','studiengang')}}:</h6>
<div class="input-group"> <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')"> <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> <i class="fa fa-caret-left" aria-hidden="true"></i>
</button> </button>
<select ref="studiengaenge" v-model="selectedStudiengang" class="form-select" @change="onStudiengangChange" :aria-label="$p.t('global/studiensemester_auswaehlen')"> <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> <option v-for="studiengang in studiengaenge" :key="studiengang.studiengang_kz" :value="studiengang.studiengang_kz" >{{studiengangTitel(studiengang)}}</option>
</select> </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')"> <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> <i class="fa fa-caret-right" aria-hidden="true"></i>
</button> </button>
</div> </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> </div>
<div class="card-body">
<ul class="list-group list-group-flush"> <div>
<li class="d-flex list-group-item" v-for="lv in lehrveranstaltung.lehrveranstaltungen"> <h6>{{$p.t('lehre','semester')}}:</h6>
<a class="fhc-link-color d-block me-auto" href="#" @click="openLvUebersicht(lv)">{{isGermanLanguage ? lv.bezeichnung : lv.bezeichnung_english}}</a> <div class="input-group">
<p>{{lv.lehrform_kurzbz}}</p> <button class="btn btn-outline-secondary" type="button" :disabled="false" @click="changeSemester(-1)" :aria-label="$p.t('global','previous')" :title="$p.t('global','previous')">
</li> <i class="fa fa-caret-left" aria-hidden="true"></i>
</ul> </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>
</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> </div>
` `
}; };
+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 // ### STUDIENGANG_INFORMATIONEN PHRASEN ENDE
array( array(
'app' => 'core', 'app' => 'core',