Merge branch 'feature-63370/AnwesenheitenMicrotuning'

This commit is contained in:
Harald Bamberger
2025-09-11 13:24:37 +02:00
9 changed files with 183 additions and 42 deletions
@@ -51,7 +51,7 @@ class LvMenu extends FHCAPI_Controller
$this->load->library("PermissionLib", null, 'PermissionLib');
$this->load->library("PhrasesLib");
$this->load->library("PhrasesLib", null, 'PhrasesLib');
$this->loadPhrases(array('global', 'lehre'));
}
@@ -333,6 +333,7 @@ class LvMenu extends FHCAPI_Controller
'id'=>'core_menu_lvinfo',
'position'=>'10',
'name'=>$this->p->t('lehre', 'lehrveranstaltungsinformation'),
'phrase' => 'lehre/lehrveranstaltungsinformation',
'icon'=>'../../../skin/images/button_lvinfo.png',
'link'=>'',
'c4_icon'=> base_url('skin/images/button_lvinfo.png'),
@@ -351,6 +352,7 @@ class LvMenu extends FHCAPI_Controller
'id'=>'core_menu_feedback',
'position'=>'60',
'name'=>$this->p->t('lehre', 'feedback'),
'phrase' => 'lehre/feedback',
'c4_icon'=> base_url('skin/images/button_feedback.png'),
'c4_link'=> base_url('feedback.php?lvid='.$lvid),
);
@@ -368,6 +370,7 @@ class LvMenu extends FHCAPI_Controller
'id'=>'core_menu_gesamtnote',
'position'=>'80',
'name'=>$this->p->t('lehre', 'gesamtnote'),
'phrase' => 'lehre/gesamtnote',
'c4_icon'=> base_url('skin/images/button_endnote.png'),
'c4_link'=> base_url('cis/private/lehre/benotungstool/lvgesamtnoteverwalten.php?lvid='.urlencode($lvid).'&stsem='.urlencode($angezeigtes_stsem))
//'c4_link'=> base_url('benotungstool/lvgesamtnoteverwalten.php?lvid='.urlencode($lvid).'&stsem='.urlencode($angezeigtes_stsem))
@@ -380,6 +383,7 @@ class LvMenu extends FHCAPI_Controller
'id'=>'core_menu_gesamtnote',
'position'=>'80',
'name'=>$this->p->t('lehre', 'gesamtnote'),
'phrase'=>'lehre/gesamtnote',
'c4_icon'=>base_url('skin/images/button_endnote.png'),
'c4_link'=>'#',
'c4_linkList'=>[[$this->p->t('lehre', 'noteneingabedeaktiviert'),'#']],
@@ -452,6 +456,7 @@ class LvMenu extends FHCAPI_Controller
'id'=>'core_menu_mailanstudierende',
'position'=>'100',
'name'=>$this->p->t('lehre', 'mail'),
'phrase' => 'lehre/mail',
'c4_icon'=>base_url('skin/images/button_feedback.png'),
'c4_icon2' => 'fa-regular fa-envelope',
'c4_link'=>$mailto,
@@ -476,6 +481,7 @@ class LvMenu extends FHCAPI_Controller
'id'=>'core_menu_abmeldung',
'position'=>'120',
'name'=>$this->p->t('lehre', 'abmelden'),
'phrase'=>'lehre/abmelden',
'c4_icon'=>base_url('skin/images/button_studiupload.png'),
'c4_link'=>base_url('abmeldung.php?lvid='.urlencode($lvid).'&stsem='.urlencode($angezeigtes_stsem)),
);
@@ -510,6 +516,7 @@ class LvMenu extends FHCAPI_Controller
'id' => 'core_menu_anerkennungNachgewiesenerKenntnisse',
'position' => '128',
'name' => $this->p->t('lehre', 'anrechnung'),
'phrase' => 'lehre/anrechnung',
'c4_icon' => base_url('skin/images/button_listen.png'),
'c4_icon2' => 'fa-regular fa-folder-open',
'c4_link' => base_url('cis.php/lehre/anrechnung/RequestAnrechnung?studiensemester='.urlencode($angezeigtes_stsem).'&lv_id='.urlencode($lvid))
@@ -527,6 +534,7 @@ class LvMenu extends FHCAPI_Controller
'id' => 'core_menu_anerkennungNachgewiesenerKenntnisse_empfehlen',
'position' => '128',
'name' => $this->p->t('lehre', 'anrechnungen'),
'phrase' => 'lehre/anrechnung',
'c4_icon'=> base_url('skin/images/button_listen.png'),
'c4_icon2' => 'fa-regular fa-folder-open',
'c4_link' => base_url('cis.php/lehre/anrechnung/ReviewAnrechnungUebersicht?studiensemester='.urlencode($angezeigtes_stsem))
+14
View File
@@ -22,5 +22,19 @@ export default {
url: '/api/frontend/v1/Ort/ContentID',
params: { ort_kurzbz: ort_kurbz }
};
},
getRooms(datum, von, bis, typ, personenanzahl = 0) {
return {
method: 'get',
url: '/api/frontend/v1/Ort/getRooms',
params: { datum, von, bis, typ, personenanzahl }
};
},
getRoomTypes() {
return {
method: 'get',
url: '/api/frontend/v1/Ort/getTypes',
params: { }
};
}
};
@@ -12,7 +12,7 @@ export default {
required:true,
},
content_id:{
type:Number,
type: [Number, String],
}
},
methods: {
@@ -129,7 +129,7 @@ export default {
template: /*html*/ `
<!-- div that contains the content -->
<!-- TODO: test with more img content from cms-->
<div v-if="imgContent"><img v-bind="imgContent"></img></div>
<div v-if="imgContent"><img v-bind="imgContent"/></div>
<div v-html="content" v-else-if="content" ></div>
<p v-else>Content was not found</p>
`,
+8 -1
View File
@@ -43,6 +43,13 @@ export default {
return menuItem.c4_link ?? null;
}
},
getMenuName(menuItem) {
if(menuItem.phrase) {
return this.$p.t(menuItem.phrase)
} else {
return menuItem.name
}
}
},
template:/*html*/`
<div v-if="!menu">{{$p.t('lehre','lehrveranstaltungsUnavailable')}}</div>
@@ -54,7 +61,7 @@ export default {
:disabled="c4_disabled(menuItem)" :data-bs-toggle="menuItem.c4_moodle_links?.length?'dropdown':null"
class="menu-entry p-2 w-100 text-wrap border border-1 rounded-3 d-flex flex-column align-items-center justify-content-center text-center text-decoration-none link h-100">
<img :src="menuItem.c4_icon" :alt="menuItem.name" />
<p class="w-100 mt-2 mb-0">{{menuItem.name}}</p>
<p class="w-100 mt-2 mb-0">{{ getMenuName(menuItem) }}</p>
<a v-for="([text,link],index) in menuItem.c4_linkList" target="_blank" :href="link" class="my-1 w-100 submenu text-decoration-none" :index="index">{{text}}</a>
</a>
<ul v-if="menuItem.c4_moodle_links?.length" class="dropdown-menu p-0" :aria-labelledby="menuItem.name">
@@ -19,6 +19,7 @@ export default {
props: {
lehrveranstaltung_id: Number,
bezeichnung: String,
bezeichnung_eng: String,
module: String,
farbe: String,
lvinfo: Boolean,
+21 -22
View File
@@ -1,6 +1,6 @@
import {CoreFilterCmpt} from "../../../components/filter/Filter.js";
import VueDatePicker from '../../vueDatepicker.js.php';
import ApiOrt from '../../../api/factory/ort.js'
export const Raumsuche = {
name: "Raumsuche",
props: {
@@ -13,6 +13,8 @@ export const Raumsuche = {
},
data() {
return {
phrasenPromise: null,
phrasenResolved: false,
tabulatorUuid: Vue.ref(0),
tableBuiltResolve: null,
tableBuiltPromise: null,
@@ -54,8 +56,8 @@ export const Raumsuche = {
columns: [
{title: Vue.computed(() => this.$p.t('rauminfo/raum_kurzbz')), field: 'ort_kurzbz', widthGrow: 1},
{title: Vue.computed(() => this.$p.t('global/bezeichnung')), field: 'bezeichnung', widthGrow: 2},
{title: Vue.computed(() => this.$p.t('global/nummer')), field: 'nummer', widthGrow: 1},
{title: Vue.computed(() => this.$p.t('global/personen')), field: 'personen', widthGrow: 1},
{title: Vue.computed(() => this.$p.t('rauminfo/raumnummer')), field: 'nummer', widthGrow: 1},
{title: Vue.computed(() => this.$p.t('rauminfo/personcap')), field: 'personen', widthGrow: 1},
{title: Vue.computed(() => this.$p.t('rauminfo/rauminfo')),
field: 'linkInfo', formatter: this.linkFormatter, widthGrow: 1},
{title: Vue.computed(() => this.$p.t('rauminfo/roomReservations')),
@@ -68,17 +70,6 @@ export const Raumsuche = {
handler: async () => {
this.tableBuiltResolve()
}
},
{
event: "cellClick",
handler: async (e, cell) => {
if((cell.column.field === 'linkInfo' || cell.column.field === 'linkRes') && cell.value){
window.open(cell.value, '_blank');
e.stopPropagation();
}
}
}
]};
},
@@ -132,7 +123,8 @@ export const Raumsuche = {
this.$refs.raumsucheTable.tabulator.setData(d);
},
loadRoomTypes() {
this.$fhcApi.factory.ort.getRoomTypes().then(res => {
this.$api.call(ApiOrt.getRoomTypes())
.then(res => {
res?.data?.forEach(type => {
type.beschreibung = type.beschreibung.replace('&amp;', '&')
})
@@ -141,7 +133,7 @@ export const Raumsuche = {
})
},
loadRooms() {
this.$fhcApi.factory.ort.getRooms(this.datum.toISOString(), this.getTimeString(this.von), this.getTimeString(this.bis), this.selectedType?.raumtyp_kurzbz ?? '', this.anzahl)
this.$api.call(ApiOrt.getRooms(this.datum.toISOString(), this.getTimeString(this.von), this.getTimeString(this.bis), this.selectedType?.raumtyp_kurzbz ?? '', this.anzahl))
.then(res => {
if(res?.data?.retval) this.setupData(res.data.retval)
})
@@ -167,6 +159,7 @@ export const Raumsuche = {
return `${hours}:${minutes}`;
},
async setupMounted() {
this.tableBuiltPromise = new Promise(this.tableResolve)
await this.tableBuiltPromise
@@ -182,7 +175,7 @@ export const Raumsuche = {
if(this.$refs.raumsucheTable) {
this.$refs.raumsucheTable.$refs.table.style.setProperty('height', h+'px')
}
}
},
computed: {
@@ -191,7 +184,8 @@ export const Raumsuche = {
}
},
created() {
this.phrasenPromise = this.$p.loadCategory(['rauminfo', 'global'])
this.phrasenPromise.then(()=> {this.phrasenResolved = true})
},
mounted() {
this.setupMounted()
@@ -239,7 +233,7 @@ export const Raumsuche = {
</VueDatePicker>
</div>
<div class="col-lg-auto">
<div class="col-12 col-lg-3">
<select ref="raumtyp" id="raumtypSelect" v-model="selectedType" class="form-select"
:aria-label="$p.t('global/studiensemester_auswaehlen')" @change="setRoute($event.target.value)">
<option :key="defaultType" selected :value="defaultType">{{defaultType.beschreibung}}</option>
@@ -248,16 +242,21 @@ export const Raumsuche = {
</div>
<div class="col-4 col-lg-2">
<InputNumber v-model="anzahl" :prefix="$p.t('rauminfo/anzahlPersonen') + ': '" inputId="anzahlInput" :min="1" :max="100" />
<div class="col-12 col-lg-3">
<InputNumber v-model="anzahl"
:prefix="$p.t('rauminfo/minCapacity') + ': '"
inputId="anzahlInput" :min="1" :max="1000"
:style="{'width': '100%'}"
/>
</div>
<div class="col-8 col-lg-2 d-flex justify-content-center align-items-center">
<div class="col-12 col-lg-2">
<button class="btn btn-primary border-0" @click="search">{{ $p.t('rauminfo/roomSearch') }} <i class="fa fa-magnifying-glass"></i></button>
</div>
</div>
<core-filter-cmpt
v-if="phrasenResolved"
@uuidDefined="handleUuidDefined"
:title="''"
ref="raumsucheTable"
@@ -23,14 +23,6 @@ export default {
this.$p.t('person/ort'),
this.event.ort_kurzbz
].join(": "));
this.event.lektor = [
this.event.lektor[0],
this.event.lektor[0],
this.event.lektor[0],
this.event.lektor[0],
this.event.lektor[0],
];
if (Array.isArray(this.event.lektor) && this.event.lektor.length > 0) {
if (this.event.lektor.length > 3) {
+5 -5
View File
@@ -106,7 +106,7 @@ export default {
setPrev() {
const thisIndex = this.allNewsList.findIndex(n=>n.news_id == this.selected.news_id)
const prevIndex = thisIndex ? thisIndex - 1 : this.allNewsList.length - 1
this.setSelected(this.allNewsList[prevIndex])
this.updateNewsContentClasses();
},
@@ -118,14 +118,14 @@ export default {
return classString
},
async setSelected(news) {
let clickedElement = document.getElementById('card-'+news.news_id);
let clickedElementIndex = this.allNewsList.indexOf(news);
let oldElementIndex = this.allNewsList.indexOf(this.selected);
const clickedElement = document.getElementById('card-'+news.news_id);
const clickedElementIndex = this.allNewsList.indexOf(news);
const oldElementIndex = this.allNewsList.indexOf(this.selected);
//if the clicked element is already active, do nothing
if(clickedElementIndex === oldElementIndex) return;
//add prev/next class to the clicked element
if(clickedElementIndex > oldElementIndex){
if(clickedElementIndex > oldElementIndex) {
clickedElement.classList.add('carousel-item-next');
}else{
clickedElement.classList.add('carousel-item-prev');
+123 -3
View File
@@ -20727,18 +20727,18 @@ array(
array(
'app' => 'core',
'category' => 'rauminfo',
'phrase' => 'anzahlPersonen',
'phrase' => 'minCapacity',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Anzahl Person",
'text' => "Mindestpersonenkapazität",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Number of People",
'text' => "Minimum person capacity",
'description' => '',
'insertvon' => 'system'
)
@@ -20764,6 +20764,46 @@ array(
)
)
),
array(
'app' => 'core',
'category' => 'rauminfo',
'phrase' => 'personcap',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Personen Kapazität",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Person Capacity",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'rauminfo',
'phrase' => 'raumnummer',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => "Raumnummer",
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => "Room Number",
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'rauminfo',
@@ -33798,6 +33838,46 @@ array(
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'antragsdatum',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Antragsdatum',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Application date',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'fileuploaddatum',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'FileUpload-Datum',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'File upload date',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
@@ -34050,6 +34130,46 @@ array(
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'tooltipAssistenzVonDatum',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Untere Datumsgrenze für das Laden von Entschuldigungsdaten',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Lower date limit for the data loading of excuse notes',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'anwesenheiten',
'category' => 'global',
'phrase' => 'tooltipAssistenzBisDatum',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Obere Datumsgrenze für das Laden von Entschuldigungsdaten',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Upper date limit for the data loading of excuse notes',
'description' => '',
'insertvon' => 'system'
)
)
),
//
// DIGITALE ANWESENHEITEN PHRASEN END
//