mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-20 00:12:15 +00:00
merge C4 cleanup
This commit is contained in:
@@ -61,7 +61,7 @@ $route['api/v1/organisation/[O|o]rganisationseinheit/(:any)'] = 'api/v1/organisa
|
||||
$route['api/v1/ressource/[B|b]etriebsmittelperson/(:any)'] = 'api/v1/ressource/betriebsmittelperson2/$1';
|
||||
$route['api/v1/system/[S|s]prache/(:any)'] = 'api/v1/system/sprache2/$1';
|
||||
|
||||
$route['Cis/Stundenplan/(:any)?'] = 'Cis/Stundenplan/index/$1';
|
||||
$route['Cis/Stundenplan/.*'] = 'Cis/Stundenplan/index/$1';
|
||||
|
||||
// load routes from extensions
|
||||
$subdir = 'application/config/extensions';
|
||||
|
||||
@@ -23,10 +23,10 @@ class Stundenplan extends Auth_Controller
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function index($lv_id = null)
|
||||
public function index()
|
||||
{
|
||||
|
||||
$viewData = array(
|
||||
'lv_id' => $lv_id,
|
||||
'uid'=>getAuthUID(),
|
||||
);
|
||||
|
||||
|
||||
@@ -153,6 +153,11 @@ class Stundenplan extends FHCAPI_Controller
|
||||
$stundenplan_data = $this->StundenplanModel->getStundenplanLVA($start_date, $end_date, $lv_id);
|
||||
$stundenplan_data = $this->getDataOrTerminateWithError($stundenplan_data) ?? [];
|
||||
$this->expand_object_information($stundenplan_data);
|
||||
|
||||
// query lv itself in case its Stundenplan is being queried and it has no entries
|
||||
$this->load->model('education/Lehrveranstaltung_model','LehrveranstaltungModel');
|
||||
$lv = getData($this->LehrveranstaltungModel->load($lv_id))[0];
|
||||
$this->addMeta('lv', $lv);
|
||||
$this->terminateWithSuccess($stundenplan_data);
|
||||
|
||||
}
|
||||
|
||||
@@ -556,16 +556,6 @@ class Lehrveranstaltung_model extends DB_Model
|
||||
*/
|
||||
public function getLvsByStudentWithGrades($student_uid, $studiensemester_kurzbz, $sprache = null, $lvid=null)
|
||||
{
|
||||
if ($sprache) {
|
||||
$sprache_qry = $this->db->compile_binds('SELECT index FROM public.tbl_sprache WHERE sprache = ?', [$sprache]);
|
||||
$bezeichnung = 'bezeichnung_mehrsprachig[(' . $sprache_qry . ')]';
|
||||
$sgbezeichnung = $sprache == 'English' ? 'COALESCE(sg.english, sg.bezeichnung)' : 'sg.bezeichnung';
|
||||
$lvbezeichnung = $sprache == 'English' ? 'COALESCE(v.bezeichnung_english, v.bezeichnung)' : 'v.bezeichnung';
|
||||
} else {
|
||||
$bezeichnung = 'bezeichnung';
|
||||
$sgbezeichnung = 'sg.bezeichnung';
|
||||
$lvbezeichnung = 'v.bezeichnung';
|
||||
}
|
||||
|
||||
$this->addDistinct();
|
||||
// TODO(chris): selects
|
||||
@@ -605,16 +595,20 @@ class Lehrveranstaltung_model extends DB_Model
|
||||
$this->addSelect('znn.positiv');
|
||||
|
||||
#$this->addSelect('splv.module');
|
||||
$this->addSelect($lvbezeichnung . ' AS bezeichnung');
|
||||
$this->addSelect($sgbezeichnung . ' AS sg_bezeichnung');
|
||||
$this->addSelect('v.bezeichnung AS bezeichnung');
|
||||
$this->addSelect('v.bezeichnung_english AS bezeichnung_eng');
|
||||
$this->addSelect('sg.bezeichnung AS sg_bezeichnung');
|
||||
$this->addSelect('sg.english AS sg_bezeichnung_eng');
|
||||
$this->addSelect('UPPER(sg.typ::VARCHAR(1) || sg.kurzbz) AS studiengang_kuerzel');
|
||||
|
||||
//also adds returns the index of the grade
|
||||
//TODO: ist zeugnissnote immer gleich wie die lvgesamtnote
|
||||
$this->addSelect('COALESCE(zn.note::numeric,gn.note::numeric) as note_index');
|
||||
$this->addSelect('COALESCE(znn.positiv,gnn.positiv) as positiv');
|
||||
$this->addSelect('COALESCE(gnn.' . $bezeichnung . ', gnn.bezeichnung, gn.note::text) AS lvnote');
|
||||
$this->addSelect('COALESCE(znn.' . $bezeichnung . ', znn.bezeichnung, zn.note::text) AS znote');
|
||||
$this->addSelect('gnn.bezeichnung_mehrsprachig AS lvnotebez');
|
||||
$this->addSelect('gnn.note AS lvnote');
|
||||
$this->addSelect('znn.bezeichnung_mehrsprachig AS znotebez');
|
||||
$this->addSelect('znn.note AS znote');
|
||||
|
||||
// TODO(chris): Potentielle Anpassung "Eine UID"
|
||||
$this->addJoin('campus.vw_student_lehrveranstaltung v', 'lehrveranstaltung_id');
|
||||
|
||||
@@ -402,6 +402,7 @@ function checkZeilenUmbruch()
|
||||
'id'=>'core_menu_mailanstudierende',
|
||||
'position'=>'100',
|
||||
'name'=>$p->t('lehre/mail'),
|
||||
'phrase'=>'lehre/mail',
|
||||
'icon'=>'../../../skin/images/button_feedback.png',
|
||||
'link'=>$mailto,
|
||||
'link_onclick'=>$link_onclick
|
||||
@@ -477,6 +478,7 @@ function checkZeilenUmbruch()
|
||||
'id'=>'core_menu_anerkennungNachgewiesenerKenntnisse',
|
||||
'position'=>'128',
|
||||
'name'=>$p->t('lehre/anrechnung'),
|
||||
'phrase'=>'lehre/anrechnung',
|
||||
'icon'=>'../../../skin/images/button_listen.png',
|
||||
'link' => APP_ROOT. 'index.ci.php/lehre/anrechnung/RequestAnrechnung?studiensemester='.urlencode($angezeigtes_stsem).'&lv_id='.urlencode($lvid)
|
||||
);
|
||||
@@ -491,6 +493,7 @@ if((!defined('CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN') || CIS_LEHRVERANSTALTU
|
||||
'id'=>'core_menu_anerkennungNachgewiesenerKenntnisse_empfehlen',
|
||||
'position'=>'128',
|
||||
'name'=>$p->t('lehre/anrechnungen'),
|
||||
'phrase'=>'lehre/anrechnung',
|
||||
'icon'=>'../../../skin/images/button_listen.png',
|
||||
'link' => APP_ROOT. 'index.ci.php/lehre/anrechnung/ReviewAnrechnungUebersicht?studiensemester='.urlencode($angezeigtes_stsem)
|
||||
);
|
||||
|
||||
+140
-10
@@ -3,13 +3,13 @@ import FhcApi from '../../plugin/FhcApi.js';
|
||||
import Phrasen from '../../plugin/Phrasen.js';
|
||||
import contrast from '../../directives/contrast.js';
|
||||
import {setScrollbarWidth} from "../../helpers/CssVarCalcHelpers.js";
|
||||
import Stundenplan from "../../components/Cis/Stundenplan/Stundenplan.js";
|
||||
import Stundenplan, {DEFAULT_MODE_STUNDENPLAN} from "../../components/Cis/Stundenplan/Stundenplan.js";
|
||||
import MylvStudent from "../../components/Cis/Mylv/Student.js";
|
||||
import Profil from "../../components/Cis/Profil/Profil.js";
|
||||
import CmsNews from "../../components/Cis/Cms/News.js";
|
||||
import CmsContent from "../../components/Cis/Cms/Content.js";
|
||||
import Info from "../../components/Cis/Mylv/Semester/Studiengang/Lv/Info.js";
|
||||
import RoomInformation from "../../components/Cis/Mylv/RoomInformation.js";
|
||||
import RoomInformation, { DEFAULT_MODE_RAUMINFO } from "../../components/Cis/Mylv/RoomInformation.js";
|
||||
|
||||
const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
|
||||
|
||||
@@ -28,11 +28,65 @@ const router = VueRouter.createRouter({
|
||||
component: Profil,
|
||||
props: true
|
||||
},
|
||||
|
||||
// Redirect old links to new format
|
||||
{
|
||||
path: `/CisVue/Cms/getRoomInformation/:ort_kurzbz`,
|
||||
path: "/CisVue/Cms/getRoomInformation/:ort_kurzbz",
|
||||
name: "RoomInformationOld",
|
||||
component: RoomInformation,
|
||||
redirect: (to) => {
|
||||
return { // redirect to longer Rauminfo url and map params
|
||||
name: "RoomInformation",
|
||||
params: { // in this case always populate other params since they are not optional
|
||||
ort_kurzbz: to.params.ort_kurzbz,
|
||||
mode: DEFAULT_MODE_RAUMINFO,
|
||||
focus_date: new Date().toISOString().split("T")[0]
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
path: `/CisVue/Cms/getRoomInformation/:mode/:focus_date/:ort_kurzbz`,
|
||||
name: 'RoomInformation',
|
||||
component: RoomInformation,
|
||||
props: true
|
||||
props: (route) => { // validate and set mode/focus date if for some reason missing
|
||||
const validModes = ["Month", "Week", "Day"];
|
||||
|
||||
// check mode string
|
||||
const mode = route.params.mode &&
|
||||
validModes.includes(route.params.mode.charAt(0).toUpperCase() + route.params.mode.slice(1).toLowerCase())
|
||||
? route.params.mode.charAt(0).toUpperCase() + route.params.mode.slice(1).toLowerCase()
|
||||
: DEFAULT_MODE_RAUMINFO;
|
||||
|
||||
// default to today date if not provided
|
||||
const d = new Date(route.params.focus_date)
|
||||
const focus_date = !isNaN(d) ? route.params.focus_date : new Date().toISOString().split("T")[0];
|
||||
|
||||
// for consistency reasons format the props into one object but actually use a new name to we dont collide with
|
||||
// existing viewData declaration written from codeigniter 3 into routerview tag
|
||||
return {
|
||||
propsViewData: {
|
||||
mode,
|
||||
focus_date,
|
||||
ort_kurzbz: route.params.ort_kurzbz
|
||||
}
|
||||
};
|
||||
},
|
||||
beforeEnter: (to, from, next) => {
|
||||
// missing mode or focus_date -> set defaults
|
||||
if (!to.params.mode || !to.params.focus_date) {
|
||||
next({
|
||||
name: "RoomInformation",
|
||||
params: {
|
||||
mode: to.params.mode || DEFAULT_MODE_RAUMINFO,
|
||||
focus_date: to.params.focus_date || new Date().toISOString().split("T")[0],
|
||||
ort_kurzbz: route.params.ort_kurzbz
|
||||
}
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: `/CisVue/Cms/Content/:content_id`,
|
||||
@@ -58,10 +112,68 @@ const router = VueRouter.createRouter({
|
||||
component: Info,
|
||||
props: true
|
||||
},
|
||||
// Redirect old links to new format
|
||||
{
|
||||
path: `/Cis/Stundenplan/:lv_id?`,
|
||||
// only trigger on first param being numeric to avoid paths like "Stundenplan/Month" entering here
|
||||
path: "/Cis/Stundenplan/:lv_id(\\d+)",
|
||||
name: "StundenplanOld",
|
||||
component: Stundenplan,
|
||||
redirect: (to) => {
|
||||
return { // redirect to longer Stundenplan url and map params
|
||||
name: "Stundenplan",
|
||||
params: {
|
||||
lv_id: to.params.lv_id
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
path: `/Cis/Stundenplan/:mode?/:focus_date?/:lv_id?`,
|
||||
name: 'Stundenplan',
|
||||
component: Stundenplan
|
||||
component: Stundenplan,
|
||||
props: (route) => { // validate and set mode/focus date if for some reason missing
|
||||
const validModes = ["Month", "Week", "Day"];
|
||||
|
||||
// check mode string
|
||||
const mode = route.params.mode &&
|
||||
validModes.includes(route.params.mode.charAt(0).toUpperCase() + route.params.mode.slice(1).toLowerCase())
|
||||
? route.params.mode.charAt(0).toUpperCase() + route.params.mode.slice(1).toLowerCase()
|
||||
: DEFAULT_MODE_STUNDENPLAN;
|
||||
|
||||
// default to today date if not provided or string forms invalid date
|
||||
const d = new Date(route.params.focus_date)
|
||||
const focus_date = !isNaN(d) ? route.params.focus_date : new Date().toISOString().split("T")[0];
|
||||
// for consistency reasons format the props into one object but actually use a new name to we dont collide with
|
||||
// existing viewData declaration written from codeigniter 3 into routerview tag
|
||||
return {
|
||||
propsViewData: {
|
||||
mode,
|
||||
focus_date,
|
||||
lv_id: route.params.lv_id
|
||||
}
|
||||
};
|
||||
},
|
||||
beforeEnter: (to, from, next) => {
|
||||
// missing mode or focus_date -> set defaults
|
||||
if (!to.params.mode || !to.params.focus_date) {
|
||||
next({
|
||||
name: "Stundenplan",
|
||||
params: {
|
||||
mode: to.params.mode || DEFAULT_MODE_STUNDENPLAN,
|
||||
focus_date: to.params.focus_date || new Date().toISOString().split("T")[0],
|
||||
lv_id: to.params.lv_id
|
||||
}
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: `/Cis4`,
|
||||
name: 'Cis4',
|
||||
component: FhcDashboard,
|
||||
props: {dashboard: 'CIS'},
|
||||
},
|
||||
{
|
||||
path: `/`,
|
||||
@@ -70,14 +182,32 @@ const router = VueRouter.createRouter({
|
||||
props: {dashboard: 'CIS'},
|
||||
},
|
||||
{
|
||||
path: `/Cis4`,
|
||||
name: 'Cis4',
|
||||
path: '/:pathMatch(.*)*',
|
||||
name: 'Fallback',
|
||||
component: FhcDashboard,
|
||||
props: {dashboard: 'CIS'},
|
||||
}
|
||||
redirect: () => {
|
||||
return {
|
||||
name: "Cis4",
|
||||
params: {
|
||||
dashboard: 'CIS'
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
router.beforeEach((to, from) => {
|
||||
// this avoids redundant routing navigation in place due to router.replace on a route with param function and
|
||||
// beforeEnter navigation guard
|
||||
|
||||
// TODO: manage the infinite forward navigation issue somehow
|
||||
if (to.fullPath === from.fullPath) {
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
||||
const app = Vue.createApp({
|
||||
name: 'FhcApp',
|
||||
data: () => ({
|
||||
@@ -111,7 +241,7 @@ const app = Vue.createApp({
|
||||
|
||||
// let click event propagate normally if we dont route internally
|
||||
const res = this.$router.resolve(route)
|
||||
if(!res?.matched?.length) return
|
||||
if(!res?.matched?.length || res.name === 'Fallback') return
|
||||
|
||||
event.preventDefault(); // Prevent browser navigation
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ export default {
|
||||
noMonthView: Boolean
|
||||
},
|
||||
watch:{
|
||||
mode(newVal) {
|
||||
this.$emit('change:mode', newVal)
|
||||
},
|
||||
selectedEvent:{
|
||||
handler(newSelectedEvent) {
|
||||
this.$emit('selectedEvent', newSelectedEvent);
|
||||
@@ -92,7 +95,8 @@ export default {
|
||||
'select:event',
|
||||
'change:range',
|
||||
'update:minimized',
|
||||
'selectedEvent'
|
||||
'selectedEvent',
|
||||
'change:offset'
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
@@ -161,12 +165,12 @@ export default {
|
||||
if (this.events && Array.isArray(this.events) && this.events.length > 0) {
|
||||
let filteredEvents = this.events.filter(event => {
|
||||
let eventDate = new CalendarDate(new Date(event.datum));
|
||||
if (this.mode == 'week')
|
||||
if (this.mode == 'week' || this.mode == 'Week')
|
||||
{
|
||||
// week view filters the elements only for the same week
|
||||
return this.focusDate.w == eventDate.w;
|
||||
}
|
||||
else if (this.mode == 'day')
|
||||
else if (this.mode == 'day' || this.mode == 'Day')
|
||||
{
|
||||
// day view filters the elements for the same day and the same week
|
||||
return this.focusDate.d == eventDate.d && this.focusDate.w == eventDate.w;
|
||||
@@ -187,17 +191,21 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setMode(mode) {
|
||||
this.mode = mode
|
||||
},
|
||||
handleInput(day) {
|
||||
this.$emit(day[0], day[1]);
|
||||
},
|
||||
},
|
||||
created() {
|
||||
const allowedInitialModes = ['years'];
|
||||
const initMode = this.initialMode.toLowerCase()
|
||||
const allowedInitialModes = ['day'];
|
||||
if (!this.noWeekView)
|
||||
allowedInitialModes.push('week');
|
||||
if (!this.noMonthView)
|
||||
allowedInitialModes.push('month');
|
||||
this.mode = allowedInitialModes[allowedInitialModes.indexOf(this.initialMode)] || allowedInitialModes.pop();
|
||||
this.mode = allowedInitialModes[allowedInitialModes.indexOf(initMode)] || allowedInitialModes.pop();
|
||||
this.date.set(new Date(this.initialDate));
|
||||
this.focusDate.set(this.date);
|
||||
},
|
||||
@@ -227,14 +235,14 @@ export default {
|
||||
}
|
||||
}).observe(this.$refs.container);
|
||||
}
|
||||
|
||||
},
|
||||
unmounted(){
|
||||
CalendarDates.cleanup();
|
||||
},
|
||||
template: /*html*/`
|
||||
<div ref="container" class="fhc-calendar card h-100" :class="sizeClass">
|
||||
<component :is="'calendar-' + mode" @updateMode="mode = $event" @change:range="$emit('change:range',$event)" @input="handleInput" >
|
||||
<component :is="'calendar-' + mode" @updateMode="mode = $event" @change:range="$emit('change:range',$event)"
|
||||
@input="handleInput" @change:offset="$emit('change:offset', $event)">
|
||||
<template #calendarDownloads>
|
||||
<slot name="calendarDownloads" ></slot>
|
||||
</template>
|
||||
|
||||
@@ -22,21 +22,23 @@ export default {
|
||||
this.focusDate.d += dir;
|
||||
this.emitRangeChanged(previousDate);
|
||||
},
|
||||
emitRangeChanged(previousDate) {
|
||||
emitRangeChanged(previousDate, mounted) {
|
||||
this.$emit('change:range', { start: previousDate, end:this.focusDate });
|
||||
},
|
||||
prev() {
|
||||
this.$refs.pane.prev();
|
||||
this.$emit('change:offset', { y: 0, m: 0, d: -1 });
|
||||
},
|
||||
next() {
|
||||
this.$refs.pane.next();
|
||||
this.$emit('change:offset', { y: 0, m: 0, d: 1 });
|
||||
},
|
||||
selectEvent(event) {
|
||||
this.$emit('input', ['select:event', event]);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.emitRangeChanged();
|
||||
mounted() {
|
||||
this.emitRangeChanged(new CalendarDate(this.focusDate.y, this.focusDate.m, this.focusDate.d -1), true);
|
||||
},
|
||||
template: /*html*/`
|
||||
<div class="fhc-calendar-day">
|
||||
|
||||
@@ -36,6 +36,7 @@ export default {
|
||||
'calendarClientHeight',
|
||||
'setSelectedEvent',
|
||||
'selectedEvent',
|
||||
'rowMinHeight'
|
||||
],
|
||||
props: {
|
||||
year: Number,
|
||||
@@ -398,7 +399,7 @@ export default {
|
||||
|
||||
|
||||
<div >
|
||||
<h1 v-if="noEventsCondition" class="m-0 text-secondary" ref="noEventsText" :style="noLvStyle">Keine Lehrveranstaltungen</h1>
|
||||
<h1 v-if="noEventsCondition" class="m-0 text-secondary" ref="noEventsText" :style="noLvStyle">{{ $p.t('lehre/noLvFound') }}</h1>
|
||||
<div class="events position-relative" :class="{'fhc-calendar-no-events-overlay':noEventsCondition}" ref="events" @mousemove="calcHourPosition" @mouseleave="hourPosition = null">
|
||||
<Transition>
|
||||
<div v-if="hourPosition && !noEventsCondition" class="position-absolute border-top small" :style="indicatorStyle">
|
||||
@@ -412,12 +413,13 @@ export default {
|
||||
</Transition>
|
||||
<div :id="hourGridIdentifier(hour)" v-for="hour in hours" :key="hour" class="position-absolute box-shadow-border" :style="hourGridStyle(hour)"></div>
|
||||
<div class="hours">
|
||||
<div v-for="hour in hours" style="min-height:100px" :key="hour" class="text-muted text-end small" :ref="'hour' + hour">{{hour}}:00</div>
|
||||
<div v-for="hour in hours" :style="'min-height:' + rowMinHeight " :key="hour" class="text-muted text-end small" :ref="'hour' + hour">{{hour}}:00</div>
|
||||
</div>
|
||||
<div v-for="(day,dayindex) in eventsPerDayAndHour" :key="day" class=" day border-start" :style="dayGridStyle(day)">
|
||||
|
||||
<div v-if="lookingAtToday && !noEventsCondition" :style="overlayStyle"></div>
|
||||
<div v-for="event in day.events" :key="event" :style="eventGridStyle(day,event)" v-contrast :selected="event.orig == selectedEvent" class="fhc-entry mx-2 small rounded overflow-hidden " >
|
||||
<div v-for="event in day.events" :key="event" :style="eventGridStyle(day,event)" v-contrast
|
||||
:selected="event.orig == selectedEvent" class="fhc-entry mx-2 small rounded overflow-hidden" >
|
||||
<!-- desktop version of the page template, parent receives slotProp mobile = false -->
|
||||
<div class="d-none d-xl-block h-100 " @click.prevent="eventClick(event)">
|
||||
<slot name="dayPage" :event="event.orig" :day="day" :mobile="false">
|
||||
|
||||
@@ -3,9 +3,9 @@ export default {
|
||||
return{
|
||||
selected: this.mode,
|
||||
modes:{
|
||||
day: { mode_bezeichnung: "Tag", icon: "fa-calendar-day" , condition:true},
|
||||
week: { mode_bezeichnung: "Woche", icon: "fa-calendar-week", condition: !this.noWeekView },
|
||||
month: { mode_bezeichnung: "Monat", icon: "fa-calendar-days", condition: !this.noMonthView },
|
||||
day: { mode_bezeichnung: "day", icon: "fa-calendar-day" , condition:true},
|
||||
week: { mode_bezeichnung: "week", icon: "fa-calendar-week", condition: !this.noWeekView },
|
||||
month: { mode_bezeichnung: "month", icon: "fa-calendar-days", condition: !this.noMonthView },
|
||||
},
|
||||
headerPadding:null,
|
||||
}
|
||||
@@ -62,7 +62,7 @@ export default {
|
||||
<div ref="viewButtons" v-if="!noWeekView && !noMonthView" :class="getHeaderClassSide" class="d-flex justify-content-center justify-content-md-end align-items-center" style="pointer-events: none;">
|
||||
<div style="pointer-events: all;">
|
||||
<div role="group" aria-label="Kalender Modus">
|
||||
<button type="button" :class="{'active':mode_kurzbz === mode}" style="margin-right: 4px;" @click.prevent="$emit('updateMode',mode_kurzbz)" class="btn btn-outline-secondary" v-for="({mode_bezeichnung,icon,condition},mode_kurzbz) in modes">
|
||||
<button type="button" :class="{'active':mode_kurzbz.toLowerCase() === mode.toLowerCase()}" style="margin-right: 4px;" @click.prevent="$emit('updateMode',mode_kurzbz)" class="btn btn-outline-secondary" v-for="({mode_bezeichnung,icon,condition},mode_kurzbz) in modes">
|
||||
<i v-if="condition" class="fa" :class="icon" ></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -28,16 +28,23 @@ export default {
|
||||
} else {
|
||||
this.focusDate.moveMonthInDirection(dir)
|
||||
}
|
||||
this.emitRangeChanged()
|
||||
},
|
||||
emitRangeChanged(mounted = false) {
|
||||
|
||||
this.$emit('change:range', {
|
||||
start: new Date(this.focusDate.y, this.focusDate.m, 1),
|
||||
end: new Date(this.focusDate.y, this.focusDate.m+1, 0)
|
||||
start: new Date(this.focusDate.y, this.focusDate.m, 1),
|
||||
end: new Date(this.focusDate.y, this.focusDate.m+1, 0),
|
||||
mounted
|
||||
});
|
||||
},
|
||||
prev() {
|
||||
this.$refs.pane.prev();
|
||||
this.$emit('change:offset', { y: 0, m: -1, d: 0 });
|
||||
},
|
||||
next() {
|
||||
this.$refs.pane.next();
|
||||
this.$emit('change:offset', { y: 0, m: 1, d: 0 });
|
||||
},
|
||||
selectDay(day) {
|
||||
let m = day.getMonth();
|
||||
@@ -53,11 +60,8 @@ export default {
|
||||
this.$emit('input', ['select:day',day])
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.$emit('change:range', {
|
||||
start: new Date(this.focusDate.y, this.focusDate.m, 1),
|
||||
end: new Date(this.focusDate.y, this.focusDate.m+1, 0)
|
||||
});
|
||||
mounted() {
|
||||
this.emitRangeChanged(true)
|
||||
},
|
||||
template: `
|
||||
<div class="fhc-calendar-month">
|
||||
|
||||
@@ -63,6 +63,10 @@ export default {
|
||||
|
||||
},
|
||||
methods: {
|
||||
handleEventClick(e, day) {
|
||||
this.selectDay(day)
|
||||
e.stopPropagation()
|
||||
},
|
||||
getDayClass(week, day) {
|
||||
let classstring = 'fhc-calendar-month-page-day text-decoration-none overflow-hidden'
|
||||
const isHighlightedWeek = this.isHighlightedWeek(week)
|
||||
@@ -150,10 +154,11 @@ export default {
|
||||
:key="day"
|
||||
:class="getDayClass(week, day)"
|
||||
>
|
||||
<span class="no" :style="getNumberStyle(day)">{{day.getDate()}}</span>
|
||||
<span @click="clickEvent(day,week)" class="no" :style="getNumberStyle(day)">{{day.getDate()}}</span>
|
||||
<span v-if="events[day.toDateString()] && events[day.toDateString()].length" class="events">
|
||||
<div @click="setSelectedEvent(event);" v-for="event in events[day.toDateString()]" :key="event.id"
|
||||
:style="{'background-color': event.color}" class="fhc-entry" :selected="event == selectedEvent" v-contrast >
|
||||
<div v-for="event in events[day.toDateString()]" :key="event.id"
|
||||
:style="{'background-color': event.color}" class="fhc-entry" :selected="event == selectedEvent"
|
||||
v-contrast @click="handleEventClick($event, day)">
|
||||
<slot name="monthPage" :event="event" :day="day" >
|
||||
<p>this is a placeholder which means that no template was passed to the Calendar Page slot</p>
|
||||
</slot>
|
||||
|
||||
@@ -20,23 +20,25 @@ export default {
|
||||
this.focusDate.d += dir * 7;
|
||||
this.emitRangeChanged();
|
||||
},
|
||||
emitRangeChanged() {
|
||||
emitRangeChanged(mounted = false) {
|
||||
let start = this.focusDate.firstDayOfWeek;
|
||||
let end = this.focusDate.lastDayOfWeek;
|
||||
this.$emit('change:range', { start, end });
|
||||
this.$emit('change:range', { start, end, mounted });
|
||||
},
|
||||
prev() {
|
||||
this.$refs.pane.prev();
|
||||
this.$emit('change:offset', { y: 0, m: 0, d: -7 });
|
||||
},
|
||||
next() {
|
||||
this.$refs.pane.next();
|
||||
this.$emit('change:offset', { y: 0, m: 0, d: 7 });
|
||||
},
|
||||
selectEvent(event) {
|
||||
this.$emit('input', ['select:event',event]);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.emitRangeChanged();
|
||||
mounted() {
|
||||
this.emitRangeChanged(true);
|
||||
},
|
||||
template: /*html*/`
|
||||
<div class="fhc-calendar-week">
|
||||
|
||||
@@ -23,7 +23,8 @@ export default {
|
||||
'noMonthView',
|
||||
'isSliding',
|
||||
'selectedEvent',
|
||||
'setSelectedEvent'
|
||||
'setSelectedEvent',
|
||||
'rowMinHeight'
|
||||
],
|
||||
props: {
|
||||
year: Number,
|
||||
@@ -49,7 +50,7 @@ export default {
|
||||
},
|
||||
getGridStyle() {
|
||||
return {
|
||||
'min-height': '100px',
|
||||
'min-height': this.rowMinHeight,
|
||||
// this.size is the magic number anyway which directs font-size,
|
||||
// which in turn influences a lot of layout
|
||||
width: '42px'
|
||||
@@ -299,7 +300,13 @@ export default {
|
||||
this.$emit('updateMode', 'month');
|
||||
}
|
||||
},
|
||||
changeToDay(day) {
|
||||
this.date.set(day);
|
||||
this.focusDate.set(day);
|
||||
this.$emit('updateMode', 'day');
|
||||
},
|
||||
dateToMinutesOfDay(day) {
|
||||
// subtract 7 from the total hours because the hours range from 7 to 24
|
||||
return Math.floor(((day.getHours()-7) * 60 + day.getMinutes()) / this.smallestTimeFrame) + 1;
|
||||
},
|
||||
weekPageClick(event, day) {
|
||||
@@ -346,7 +353,7 @@ export default {
|
||||
<div ref="page" class="fhc-calendar-week-page" style="min-width: 700px;">
|
||||
<div class="d-flex flex-column">
|
||||
<div class="fhc-calendar-week-page-header d-grid border-2 border-bottom text-center" :style="pageHeaderStyle" >
|
||||
<div type="button" v-for="day in days" :key="day" class="flex-grow-1" :title="dayText[day]?.heading" @click.prevent="changeToMonth(day)">
|
||||
<div type="button" v-for="day in days" :key="day" class="flex-grow-1" :title="dayText[day]?.heading" @click.prevent="changeToDay(day)">
|
||||
<div class="fw-bold">{{dayText[day]?.tag}}</div>
|
||||
<a href="#" class="small text-secondary text-decoration-none" >{{dayText[day]?.datum}}</a>
|
||||
</div>
|
||||
|
||||
@@ -8,8 +8,6 @@ export default {
|
||||
'size',
|
||||
'focusDate'
|
||||
],
|
||||
data() {
|
||||
},
|
||||
computed: {
|
||||
weeks(){
|
||||
return [...Array(this.focusDate.numWeeks).keys()].map(i => i + 1);
|
||||
@@ -34,7 +32,7 @@ export default {
|
||||
},
|
||||
},
|
||||
template: `
|
||||
<div class="fhc-calendar-weeks">
|
||||
<div class="fhc-calendar-weeks h-100">
|
||||
<calendar-header :title="title" @prev="prev" @next="next" @click="$emit('updateMode', 'years')" @updateMode="$emit('updateMode', $event)" />
|
||||
<div class="d-flex flex-wrap">
|
||||
<div v-for="(week, key) in weeks" :key="key" class="d-grid col-2">
|
||||
|
||||
@@ -41,9 +41,11 @@ export default {
|
||||
},
|
||||
prev() {
|
||||
this.$refs.pane.prev();
|
||||
this.$emit('change:offset', { y: -1, m: 0, d: 0 });
|
||||
},
|
||||
next() {
|
||||
this.$refs.pane.next();
|
||||
this.$emit('change:offset', { y: 1, m: 0, d: 0 });
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
@@ -18,6 +18,13 @@ export default {
|
||||
return [...Array(this.end - this.start).keys()].map(i => i + this.start);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const container = document.getElementById("calendarContainer")
|
||||
if(container) {
|
||||
container.style['overflow-y'] = 'scroll'
|
||||
container.style['overflow-x'] = 'auto'
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div class="fhc-calendar-years-page d-flex flex-wrap">
|
||||
<div v-for="year in years" :key="year" class="d-grid col-4">
|
||||
|
||||
@@ -56,11 +56,11 @@ export default {
|
||||
},
|
||||
},
|
||||
template:/*html*/`
|
||||
<div v-if="!menu">No Menu available</div>
|
||||
<div v-if="!menu">{{$p.t('lehre','lehrveranstaltungsUnavailable')}}</div>
|
||||
<div id="cis-menu" v-else>
|
||||
<div class="container" :class="containerStyles">
|
||||
<div class="row g-2 justify-content-center" :class="rowStyles">
|
||||
<div style="min-height:150px; min-width:150px;" class="col-12 col-lg-6 col-xl-4" v-for="(menuItem, index) in menu" :key="index">
|
||||
<div style="min-height:150px; min-width:150px;" class="col-12 col-lg-6 col-xl-4" v-for="(menuItem, index) in menu" :key="index">
|
||||
<a :id="menuItem.name" :class="{'dropdown-toggle':menuItem.c4_moodle_links?.length }" role="button" :href="c4_link(menuItem)"
|
||||
: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-dark h-100">
|
||||
|
||||
@@ -68,7 +68,7 @@ export default {
|
||||
return BsModal.popup.bind(this)(null, options);
|
||||
},
|
||||
template: /*html*/ `
|
||||
<bs-modal ref="modalContainer" @showBsModal="onModalShow" @hideBsModal="onModalHide" v-bind="$props" :bodyClass="''" dialogClass='modal-lg' class="bootstrap-alert" backdrop="false" >
|
||||
<bs-modal ref="modalContainer" @showBsModal="onModalShow" @hideBsModal="onModalHide" v-bind="$props" :bodyClass="''" dialogClass='modal-lg' class="bootstrap-alert" :backdrop="false" >
|
||||
<template v-slot:title>
|
||||
<template v-if="event?.type=='moodle'">{{event.titel}}</template>
|
||||
<template v-else-if="event.titel">{{ event.titel + ' - ' + event.lehrfach_bez + ' [' + event.ort_kurzbz+']'}}</template>
|
||||
@@ -85,7 +85,7 @@ export default {
|
||||
</h3>
|
||||
<lv-info :event="event"></lv-info>
|
||||
<template v-if="showMenu && this.menu">
|
||||
<h3 >Lehrveranstaltungs Menu</h3>
|
||||
<h3>{{$p.t('lehre','lehrveranstaltungsmenue')}}</h3>
|
||||
<lv-menu :menu="menu"></lv-menu>
|
||||
</template>
|
||||
</template>
|
||||
@@ -95,4 +95,4 @@ export default {
|
||||
</template>
|
||||
<!-- end of optional footer -->
|
||||
</bs-modal>`,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -3,25 +3,41 @@ import CalendarDate from "../../../composables/CalendarDate.js";
|
||||
import LvModal from "../../../components/Cis/Mylv/LvModal.js";
|
||||
import LvInfo from "../../../components/Cis/Mylv/LvInfo.js"
|
||||
|
||||
export default{
|
||||
export const DEFAULT_MODE_RAUMINFO = 'Week'
|
||||
|
||||
const RoomInformation = {
|
||||
name: "RoomInformation",
|
||||
props:{
|
||||
ort_kurzbz: {
|
||||
type: String,
|
||||
required: true,
|
||||
}
|
||||
propsViewData: {
|
||||
type: Object
|
||||
},
|
||||
rowMinHeight: {
|
||||
type: String,
|
||||
default: '100px'
|
||||
},
|
||||
eventMaxHeight: {
|
||||
type: String,
|
||||
default: '125px'
|
||||
}
|
||||
},
|
||||
components: {
|
||||
FhcCalendar,
|
||||
LvModal,
|
||||
LvInfo,
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
rowMinHeight: this.rowMinHeight,
|
||||
eventMaxHeight: this.eventMaxHeight
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
events: null,
|
||||
calendarMode: DEFAULT_MODE_RAUMINFO,
|
||||
calendarDate: new CalendarDate(new Date()),
|
||||
currentlySelectedEvent: null,
|
||||
currentDay: new Date(),
|
||||
currentDay: this.propsViewData?.focus_date ? new Date(this.propsViewData.focus_date) : new Date(),
|
||||
minimized: false,
|
||||
|
||||
}
|
||||
@@ -43,6 +59,17 @@ export default{
|
||||
return this.calendarDateToString(this.calendarDate.cdLastDayOfCalendarMonth);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'propsViewData.ort_kurzbz'(newVal) {
|
||||
// relevant if ort_kurzbz can be changed from within this component
|
||||
},
|
||||
'propsViewData.mode'(newVal) {
|
||||
if(this.$refs.calendar) this.$refs.calendar.setMode(newVal)
|
||||
},
|
||||
'propsViewData.focus_date'(newVal) {
|
||||
this.currentDate = new Date(newVal)
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
setSelectedEvent: function(event){
|
||||
this.currentlySelectedEvent = event;
|
||||
@@ -50,9 +77,59 @@ export default{
|
||||
getLvID: function () {
|
||||
this.lv_id = window.location.pathname
|
||||
},
|
||||
selectDay: function (day) {
|
||||
selectDay: function(day){
|
||||
const date = day.getFullYear() + "-" +
|
||||
String(day.getMonth() + 1).padStart(2, "0") + "-" +
|
||||
String(day.getDate()).padStart(2, "0");
|
||||
|
||||
this.$router.push({
|
||||
name: "RoomInformation",
|
||||
params: {
|
||||
mode: this.calendarMode,
|
||||
focus_date: date,
|
||||
ort_kurzbz: this.propsViewData.ort_kurzbz
|
||||
}
|
||||
})
|
||||
|
||||
this.currentDay = day;
|
||||
},
|
||||
handleOffset: function(offset) {
|
||||
this.currentDay = new Date(
|
||||
this.currentDay.getFullYear() + offset.y,
|
||||
this.currentDay.getMonth() + offset.m,
|
||||
this.currentDay.getDate() + offset.d
|
||||
)
|
||||
|
||||
const date = this.currentDay.getFullYear() + "-" +
|
||||
String(this.currentDay.getMonth() + 1).padStart(2, "0") + "-" +
|
||||
String(this.currentDay.getDate()).padStart(2, "0");
|
||||
|
||||
this.$router.push({
|
||||
name: "Stundenplan",
|
||||
params: {
|
||||
mode: this.calendarMode,
|
||||
focus_date: date,
|
||||
lv_id: this.propsViewData?.lv_id || null
|
||||
}
|
||||
})
|
||||
},
|
||||
handleChangeMode(mode) {
|
||||
const modeCapitalized = mode.charAt(0).toUpperCase() + mode.slice(1)
|
||||
const date = this.currentDay.getFullYear() + "-" +
|
||||
String(this.currentDay.getMonth() + 1).padStart(2, "0") + "-" +
|
||||
String(this.currentDay.getDate()).padStart(2, "0");
|
||||
|
||||
this.$router.push({
|
||||
name: "RoomInformation",
|
||||
params: {
|
||||
mode: modeCapitalized,
|
||||
focus_date: date,
|
||||
ort_kurzbz: this.propsViewData.ort_kurzbz
|
||||
}
|
||||
})
|
||||
|
||||
this.calendarMode = mode
|
||||
},
|
||||
showModal: function (event) {
|
||||
this.currentlySelectedEvent = event;
|
||||
Vue.nextTick(() => {
|
||||
@@ -86,8 +163,8 @@ export default{
|
||||
|
||||
// bundles the room_events and the reservierungen together into the this.events array
|
||||
Promise.allSettled([
|
||||
this.$fhcApi.factory.stundenplan.getRoomInfo(this.ort_kurzbz, this.monthFirstDay, this.monthLastDay),
|
||||
this.$fhcApi.factory.stundenplan.getOrtReservierungen(this.ort_kurzbz, this.monthFirstDay, this.monthLastDay)
|
||||
this.$fhcApi.factory.stundenplan.getRoomInfo(this.propsViewData.ort_kurzbz, this.monthFirstDay, this.monthLastDay),
|
||||
this.$fhcApi.factory.stundenplan.getOrtReservierungen(this.propsViewData.ort_kurzbz, this.monthFirstDay, this.monthLastDay)
|
||||
]).then((result) => {
|
||||
let promise_events = [];
|
||||
result.forEach((promise_result) => {
|
||||
@@ -120,10 +197,22 @@ export default{
|
||||
this.loadEvents();
|
||||
},
|
||||
template: /*html*/`
|
||||
<h2>Room Information {{ ort_kurzbz }}</h2>
|
||||
<h2>{{ $p.t('rauminfo/rauminfo') }} {{ propsViewData.ort_kurzbz }}</h2>
|
||||
<hr>
|
||||
<lv-modal v-if="currentlySelectedEvent" :showMenu="false" :event="currentlySelectedEvent" ref="lvmodal" />
|
||||
<fhc-calendar @selectedEvent="setSelectedEvent" :initial-date="currentDay" @change:range="updateRange" :events="events" initial-mode="week" show-weeks @select:day="selectDay" v-model:minimized="minimized">
|
||||
<fhc-calendar
|
||||
ref="calendar"
|
||||
@selectedEvent="setSelectedEvent"
|
||||
:initial-date="currentDay"
|
||||
@change:range="updateRange"
|
||||
@change:offset="handleOffset"
|
||||
:events="events"
|
||||
:initial-mode="propsViewData.mode"
|
||||
show-weeks
|
||||
@select:day="selectDay"
|
||||
@change:mode="handleChangeMode"
|
||||
v-model:minimized="minimized"
|
||||
>
|
||||
<template #monthPage="{event,day}">
|
||||
<span >
|
||||
{{event.topic}}
|
||||
@@ -139,15 +228,15 @@ export default{
|
||||
<template #dayPage="{event,day,mobile}">
|
||||
<div @click="mobile? showModal(event?.orig):null" type="button" class="fhc-entry border border-secondary border row h-100 justify-content-center align-items-center text-center">
|
||||
<div class="col ">
|
||||
<p>Lehrveranstaltung:</p>
|
||||
<p>{{ $p.t('lehre/lehrveranstaltung') }}:</p>
|
||||
<p class="m-0">{{event?.orig.topic}}</p>
|
||||
</div>
|
||||
<div class="col ">
|
||||
<p>Lektor:</p>
|
||||
<p>{{ $p.t('lehre/lektor') }}:</p>
|
||||
<p class="m-0" v-for="lektor in event?.orig.lektor">{{lektor.kurzbz}}</p>
|
||||
</div>
|
||||
<div class="col ">
|
||||
<p>Ort: </p>
|
||||
<p>{{ $p.t('profil/Ort') }}: </p>
|
||||
<p class="m-0">{{event?.orig.ort_kurzbz}}</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -155,12 +244,14 @@ export default{
|
||||
<template #pageMobilContent>
|
||||
<h3 >{{$p.t('lvinfo','lehrveranstaltungsinformationen')}}</h3>
|
||||
<div class="w-100">
|
||||
<lv-info :event="currentlySelectedEvent" />
|
||||
<lv-info :event="currentlySelectedEvent" />
|
||||
</div>
|
||||
</template>
|
||||
<template #pageMobilContentEmpty >
|
||||
<h3>Keine Raum Reservierung</h3>
|
||||
<h3>{{$p.t('rauminfo','keineRaumReservierung')}}</h3>
|
||||
</template>
|
||||
</fhc-calendar>
|
||||
`,
|
||||
};
|
||||
};
|
||||
|
||||
export default RoomInformation
|
||||
@@ -22,7 +22,8 @@ export default {
|
||||
lv.studiengang_kz + '#' + lv.semester,
|
||||
{
|
||||
studiengang_kz: lv.studiengang_kz,
|
||||
bezeichnung: lv.sg_bezeichnung,
|
||||
bezeichnung: lv.sg_bezeichnung,
|
||||
sg_bezeichnung_eng: lv.sg_bezeichnung_eng,
|
||||
kuerzel: lv.studiengang_kuerzel,
|
||||
semester: lv.semester
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ export default {
|
||||
bezeichnung: String,
|
||||
kuerzel: String,
|
||||
semester: [String,Number],
|
||||
lvs: Array
|
||||
lvs: Array,
|
||||
sg_bezeichnung_eng: String
|
||||
},
|
||||
computed: {
|
||||
lehrveranstaltungen() {
|
||||
@@ -32,7 +33,7 @@ export default {
|
||||
},
|
||||
template: `<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title mb-3">{{bezeichnung}} - {{kuerzel}}
|
||||
<h4 class="card-title mb-3">{{$p.user_language.value === 'English' ? sg_bezeichnung_eng : bezeichnung}} - {{kuerzel}}
|
||||
<small>{{semester}}.{{$p.t('lehre/semester')}}</small>
|
||||
</h4>
|
||||
<div class="row">
|
||||
|
||||
@@ -21,7 +21,9 @@ export default {
|
||||
lvinfo: Boolean,
|
||||
benotung: Boolean,
|
||||
lvnote: String,
|
||||
lvnotebez: Array,
|
||||
znote: String,
|
||||
znotebez: Array,
|
||||
studiengang_kuerzel: String,
|
||||
semester: [String, Number],
|
||||
orgform_kurzbz: String,
|
||||
@@ -29,7 +31,7 @@ export default {
|
||||
ects: String,
|
||||
incoming: Number,
|
||||
positiv: Boolean,
|
||||
note_index: String,
|
||||
note_index: String
|
||||
},
|
||||
data: () => {
|
||||
return {
|
||||
@@ -66,7 +68,12 @@ export default {
|
||||
return bodyStyle;
|
||||
},
|
||||
grade() {
|
||||
return this.benotung ? this.znote || this.lvnote || null : null;
|
||||
const languageIndex = this.$p.user_language.value === 'English' ? 1 : 0
|
||||
if(this.benotung && this.znotebez?.length) {
|
||||
return this.znotebez[languageIndex]
|
||||
} else if(this.benotung && this.lvnotebez?.length) {
|
||||
return this.lvnotebez[languageIndex]
|
||||
} else return null
|
||||
},
|
||||
LvHasPruefungenInformation(){
|
||||
return this.pruefungenData && this.pruefungenData.length > 0;
|
||||
@@ -122,6 +129,7 @@ export default {
|
||||
LvInfo.popup({
|
||||
lehrveranstaltung_id: this.lehrveranstaltung_id,
|
||||
bezeichnung: this.bezeichnung,
|
||||
bezeichnung_eng: this.bezeichnung_eng,
|
||||
studiengang_kuerzel: this.studiengang_kuerzel,
|
||||
semester: this.semester,
|
||||
studien_semester: this.studien_semester,
|
||||
@@ -159,8 +167,8 @@ export default {
|
||||
|
||||
<div class="p-2" :class="is_organisatorische_einheit?'':'card-header'">
|
||||
<!-- {{module}} if the module of the lv is important then query the module from the api endpoint for LV-->
|
||||
<h6 class="fw-bold" v-if="is_organisatorische_einheit" >Organisatorische Einheit:</h6>
|
||||
<h6 class="mb-0">{{bezeichnung}}</h6>
|
||||
<h6 class="fw-bold" v-if="is_organisatorische_einheit" >{{ $p.t('lehre/organisationseinheit') }}:</h6>
|
||||
<h6 class="mb-0">{{$p.user_language.value === 'English' ? bezeichnung_eng : bezeichnung}}</h6>
|
||||
</div>
|
||||
<div v-if="!emptyMenu" class="card-body " :style="bodyStyle">
|
||||
<template v-if="menu">
|
||||
@@ -176,7 +184,7 @@ export default {
|
||||
:class="{'link-dark':menuItem.c4_link, 'unavailable':!menuItem.c4_link, 'dropdown-toggle':menuItem.c4_moodle_links?.length }"
|
||||
:target="menuItem.c4_target"
|
||||
:href="c4_link(menuItem) ? c4_link(menuItem) : null">
|
||||
{{menuItem.name}}
|
||||
{{ menuItem.phrase ? $p.t(menuItem.phrase) : menuItem.name}}
|
||||
</a>
|
||||
</div>
|
||||
<ul v-if="menuItem.c4_moodle_links?.length" class="dropdown-menu p-0" :aria-labelledby="'moodle_links_'+lehrveranstaltung_id">
|
||||
@@ -197,14 +205,14 @@ export default {
|
||||
<template v-if="LvHasPruefungenInformation">
|
||||
<a href="#" class="col-auto text-start text-decoration-none" @click.prevent="openPruefungen">
|
||||
<i class="fa fa-check text-success" v-if="positiv"></i>
|
||||
<span class="ps-1" :style="'color:'+gradeColor">{{ grade || p.t('lehre/noGrades') }}</span>
|
||||
<span class="ps-1" :style="'color:'+gradeColor">{{ grade || $p.t('lehre/noGrades') }}</span>
|
||||
</a>
|
||||
</template>
|
||||
<!-- template for the LV with no pruefungen -->
|
||||
<template v-else>
|
||||
<span class="col-auto text-start text-decoration-none" >
|
||||
<i class="fa fa-check text-success" v-if="positiv"></i>
|
||||
<span class="ps-1" :style="'color:'+gradeColor">{{ grade || p.t('lehre/noGrades') }}</span>
|
||||
<span class="ps-1" :style="'color:'+gradeColor">{{ grade || $p.t('lehre/noGrades') }}</span>
|
||||
</span>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@@ -103,7 +103,7 @@ export default {
|
||||
<button class="btn btn-outline-secondary" type="button" :disabled="currentIsFirst" @click="prevSem">
|
||||
<i class="fa fa-caret-left" aria-hidden="true"></i>
|
||||
</button>
|
||||
<select ref="studiensemester" v-model="currentSemester" class="form-select" :aria-label="p.t('global/studiensemester_auswaehlen')" @change="setHash($event.target.value)">
|
||||
<select ref="studiensemester" v-model="currentSemester" class="form-select" :aria-label="$p.t('global/studiensemester_auswaehlen')" @change="setHash($event.target.value)">
|
||||
<option v-for="semester in studiensemester" :key="semester.studiensemester_kurzbz">{{semester.studiensemester_kurzbz}}</option>
|
||||
</select>
|
||||
<button class="btn btn-outline-secondary" type="button" :disabled="currentIsLast" @click="nextSem">
|
||||
@@ -113,7 +113,7 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
<div class="alert alert-danger" role="alert" v-else>
|
||||
{{p.t('lehre/noLvFound')}}
|
||||
{{$p.t('lehre/noLvFound')}}
|
||||
</div>
|
||||
<mylv-semester v-bind="current"/>
|
||||
</div>
|
||||
|
||||
@@ -181,7 +181,7 @@ export default {
|
||||
return BsModal.popup(null, options);
|
||||
},
|
||||
template: /*html*/ `
|
||||
<bs-modal v-show="!loading" ref="modalContainer" v-bind="$props" body-class="" dialog-class="modal-lg" class="bootstrap-alert" backdrop="false">
|
||||
<bs-modal v-show="!loading" ref="modalContainer" v-bind="$props" body-class="" dialog-class="modal-lg" class="bootstrap-alert" :backdrop="false">
|
||||
<template v-if="title" v-slot:title>{{title}}</template>
|
||||
<template v-slot:default>
|
||||
<div>
|
||||
|
||||
@@ -108,7 +108,7 @@ export default {
|
||||
},
|
||||
template: /*html*/ `
|
||||
|
||||
<bs-modal v-show="!loading" ref="modalContainer" v-bind="$props" body-class="" dialog-class="modal-lg" class="bootstrap-alert" backdrop="false" >
|
||||
<bs-modal v-show="!loading" ref="modalContainer" v-bind="$props" body-class="" dialog-class="modal-lg" class="bootstrap-alert" :backdrop="false" >
|
||||
|
||||
<template v-slot:title>
|
||||
{{title}}
|
||||
|
||||
@@ -5,25 +5,43 @@ import LvInfo from "../Mylv/LvInfo.js"
|
||||
import LvMenu from "../Mylv/LvMenu.js"
|
||||
import moodleSvg from "../../../helpers/moodleSVG.js"
|
||||
|
||||
export const Stundenplan = {
|
||||
export const DEFAULT_MODE_STUNDENPLAN = 'Week'
|
||||
|
||||
const Stundenplan = {
|
||||
name: 'Stundenplan',
|
||||
data() {
|
||||
return {
|
||||
events: null,
|
||||
calendarMode: this.propsViewData?.mode ?? DEFAULT_MODE_STUNDENPLAN,
|
||||
calendarDate: new CalendarDate(new Date()),
|
||||
eventCalendarDate: new CalendarDate(new Date()),
|
||||
currentlySelectedEvent: null,
|
||||
currentDay: new Date(),
|
||||
currentDay: this.propsViewData?.focus_date ? new Date(this.propsViewData.focus_date) : new Date(),
|
||||
lv: null,
|
||||
minimized: false,
|
||||
studiensemester_kurzbz:null,
|
||||
studiensemester_start:null,
|
||||
studiensemester_ende:null,
|
||||
uid:null,
|
||||
studiensemester_kurzbz: null,
|
||||
studiensemester_start: null,
|
||||
studiensemester_ende: null,
|
||||
uid: null
|
||||
}
|
||||
},
|
||||
props: [
|
||||
"viewData",
|
||||
],
|
||||
props: {
|
||||
propsViewData: Object,
|
||||
rowMinHeight: {
|
||||
type: String,
|
||||
default: '100px'
|
||||
},
|
||||
eventMaxHeight: {
|
||||
type: String,
|
||||
default: '125px'
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
rowMinHeight: this.rowMinHeight,
|
||||
eventMaxHeight: this.eventMaxHeight
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
weekFirstDay: {
|
||||
handler: async function (newValue) {
|
||||
@@ -34,6 +52,17 @@ export const Stundenplan = {
|
||||
this.studiensemester_ende = ende;
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
// forward/backward on history entries happening in stundenplan
|
||||
'propsViewData.lv_id'(newVal) {
|
||||
// relevant if lv_id can be changed from within this component
|
||||
},
|
||||
'propsViewData.mode'(newVal) {
|
||||
if(this.$refs.calendar) this.$refs.calendar.setMode(newVal)
|
||||
},
|
||||
'propsViewData.focus_date'(newVal) {
|
||||
// todo: navigate around with date in current mode
|
||||
this.currentDate = new Date(newVal)
|
||||
}
|
||||
},
|
||||
components: {
|
||||
@@ -47,13 +76,17 @@ export const Stundenplan = {
|
||||
let ende = new Date(this.studiensemester_ende);
|
||||
ende = Math.floor(ende.getTime() / 1000);
|
||||
|
||||
let download_link = (format, version = "", target = "") => `${FHC_JS_DATA_STORAGE_OBJECT.app_root}cis/private/lvplan/stpl_kalender.php?type=student&pers_uid=${this.uid}&begin=${start}&ende=${ende}&format=${format}${version ? '&version=' + version : ''}${target ? '&target=' + target : ''}`;
|
||||
return [{ title: "excel", icon: 'fa-solid fa-file-excel', link: download_link('excel') }, { title: "csv", icon: 'fa-solid fa-file-csv', link: download_link('csv') }, { title: "ical1", icon: 'fa-regular fa-calendar', link: download_link('ical', '1', 'ical') }, { title: "ical2", icon: 'fa-regular fa-calendar', link: download_link('ical', '2', 'ical') }];
|
||||
},
|
||||
lv_id() { // computed so we can theoretically change path/lva selection and reload without page refresh
|
||||
const pathParts = window.location.pathname.split('/').filter(Boolean);
|
||||
const id = pathParts[pathParts.length - 1];
|
||||
return id && !isNaN(Number(id)) ? id : null; // only return id if it is a number string since the path might contain invalid elements
|
||||
let download_link =
|
||||
(format, version = "", target = "") =>
|
||||
`${FHC_JS_DATA_STORAGE_OBJECT.app_root}cis/private/lvplan/stpl_kalender.php?type=student&pers_uid=
|
||||
${this.uid}&begin=${start}&ende=${ende}&format=${format}
|
||||
${version ? '&version=' + version : ''}${target ? '&target=' + target : ''}`;
|
||||
return [
|
||||
{ title: "excel", icon: 'fa-solid fa-file-excel', link: download_link('excel') },
|
||||
{ title: "csv", icon: 'fa-solid fa-file-csv', link: download_link('csv') },
|
||||
{ title: "ical1", icon: 'fa-regular fa-calendar', link: download_link('ical', '1', 'ical') },
|
||||
{ title: "ical2", icon: 'fa-regular fa-calendar', link: download_link('ical', '2', 'ical') }
|
||||
];
|
||||
},
|
||||
weekFirstDay: function () {
|
||||
return this.calendarDateToString(this.calendarDate.cdFirstDayOfWeek);
|
||||
@@ -67,7 +100,6 @@ export const Stundenplan = {
|
||||
monthLastDay: function () {
|
||||
return this.calendarDateToString(this.eventCalendarDate.cdLastDayOfCalendarMonth);
|
||||
},
|
||||
|
||||
},
|
||||
methods:{
|
||||
fetchStudiensemesterDetails: async function (date) {
|
||||
@@ -85,23 +117,88 @@ export const Stundenplan = {
|
||||
this.currentlySelectedEvent = event;
|
||||
},
|
||||
selectDay: function(day){
|
||||
const date = day.getFullYear() + "-" +
|
||||
String(day.getMonth() + 1).padStart(2, "0") + "-" +
|
||||
String(day.getDate()).padStart(2, "0");
|
||||
const capitalizedMode = this.calendarMode[0].toUpperCase() + this.calendarMode.slice(1);
|
||||
const isMonthMode = capitalizedMode === 'Month'
|
||||
const isInCurrentMonth = day.getMonth() == this.currentDay.getMonth()
|
||||
|
||||
if(isMonthMode && isInCurrentMonth) {
|
||||
this.$router.replace({
|
||||
name: "Stundenplan",
|
||||
params: {
|
||||
mode: capitalizedMode,
|
||||
focus_date: date,
|
||||
lv_id: this.propsViewData?.lv_id || null
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.$router.push({
|
||||
name: "Stundenplan",
|
||||
params: {
|
||||
mode: capitalizedMode,
|
||||
focus_date: date,
|
||||
lv_id: this.propsViewData?.lv_id || null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.currentDay = day;
|
||||
},
|
||||
handleOffset: function(offset) {
|
||||
this.currentDay = new Date(
|
||||
this.currentDay.getFullYear() + offset.y,
|
||||
this.currentDay.getMonth() + offset.m,
|
||||
this.currentDay.getDate() + offset.d
|
||||
)
|
||||
|
||||
const date = this.currentDay.getFullYear() + "-" +
|
||||
String(this.currentDay.getMonth() + 1).padStart(2, "0") + "-" +
|
||||
String(this.currentDay.getDate()).padStart(2, "0");
|
||||
|
||||
this.$router.push({
|
||||
name: "Stundenplan",
|
||||
params: {
|
||||
mode: this.calendarMode[0].toUpperCase() + this.calendarMode.slice(1),
|
||||
focus_date: date,
|
||||
lv_id: this.propsViewData?.lv_id || null
|
||||
}
|
||||
})
|
||||
},
|
||||
handleChangeMode(mode) {
|
||||
let m = mode[0].toUpperCase() + mode.slice(1)
|
||||
if(m === this.calendarMode) return
|
||||
const date = this.currentDay.getFullYear() + "-" +
|
||||
String(this.currentDay.getMonth() + 1).padStart(2, "0") + "-" +
|
||||
String(this.currentDay.getDate()).padStart(2, "0");
|
||||
|
||||
this.$router.push({
|
||||
name: "Stundenplan",
|
||||
params: {
|
||||
mode: m,
|
||||
focus_date: date,
|
||||
lv_id: this.propsViewData?.lv_id ?? null
|
||||
}
|
||||
})
|
||||
this.calendarMode = m
|
||||
},
|
||||
showModal: function(event){
|
||||
this.currentlySelectedEvent = event;
|
||||
Vue.nextTick(() => {
|
||||
this.$refs.lvmodal.show();
|
||||
});
|
||||
},
|
||||
updateRange: function ({start,end}) {
|
||||
|
||||
updateRange: function ({start,end, mounted}) {
|
||||
let checkDate = (date) => {
|
||||
return date.m != this.eventCalendarDate.m || date.y != this.eventCalendarDate.y;
|
||||
}
|
||||
this.calendarDate = new CalendarDate(end);
|
||||
|
||||
// only load month data if the month or year has changed
|
||||
if (checkDate(new CalendarDate(start)) && checkDate(new CalendarDate(end))){
|
||||
// or we receive a reload flag from the mounted routine of the components
|
||||
// or this handler is being called from the mounted lifecycle of a component
|
||||
if (mounted || (checkDate(new CalendarDate(start)) && checkDate(new CalendarDate(end)))){
|
||||
// reset the events before querying the new events to activate the loading spinner
|
||||
this.events = null;
|
||||
this.eventCalendarDate = new CalendarDate(end);
|
||||
@@ -118,14 +215,16 @@ export const Stundenplan = {
|
||||
},
|
||||
loadEvents: function(){
|
||||
Promise.allSettled([
|
||||
this.$fhcApi.factory.stundenplan.getStundenplan(this.monthFirstDay, this.monthLastDay, this.viewData.lv_id),
|
||||
this.$fhcApi.factory.stundenplan.getStundenplan(this.monthFirstDay, this.monthLastDay, this.propsViewData.lv_id),
|
||||
this.$fhcApi.factory.stundenplan.getStundenplanReservierungen(this.monthFirstDay, this.monthLastDay),
|
||||
this.loadMoodleEvents(this.monthFirstDay, this.monthLastDay)
|
||||
]).then((result) => {
|
||||
let promise_events = [];
|
||||
result.forEach((promise_result) => {
|
||||
if (promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success") {
|
||||
|
||||
|
||||
if(promise_result.value.meta?.lv) this.lv = promise_result.value.meta.lv
|
||||
|
||||
let data = promise_result.value.data;
|
||||
// adding additional information to the events
|
||||
if (data && data.forEach) {
|
||||
@@ -213,16 +312,32 @@ export const Stundenplan = {
|
||||
.then(data=>{
|
||||
this.uid = data.uid;
|
||||
})
|
||||
this.loadEvents();
|
||||
|
||||
},
|
||||
beforeUnmount() {
|
||||
if(this.$refs.lvmodal) this.$refs.lvmodal.hide()
|
||||
},
|
||||
template:/*html*/`
|
||||
<h2>{{$p.t('lehre/stundenplan')}}</h2>
|
||||
<h2>
|
||||
{{$p.t('lehre/stundenplan')}}
|
||||
<span style="padding-left: 0.4em;" v-show="studiensemester_kurzbz">{{studiensemester_kurzbz}}</span>
|
||||
<span style="padding-left: 0.5em;" v-show="propsViewData?.lv_id && lv"> {{ $p.user_language.value === 'German' ? lv?.bezeichnung : lv?.bezeichnung_english}}</span>
|
||||
</h2>
|
||||
<hr>
|
||||
<lv-modal v-if="currentlySelectedEvent" :event="currentlySelectedEvent" ref="lvmodal" />
|
||||
<fhc-calendar @selectedEvent="setSelectedEvent" :initial-date="currentDay" @change:range="updateRange" :events="events" initial-mode="week" show-weeks @select:day="selectDay" v-model:minimized="minimized">
|
||||
<fhc-calendar
|
||||
ref="calendar"
|
||||
@selectedEvent="setSelectedEvent"
|
||||
:initial-date="currentDay"
|
||||
@change:range="updateRange"
|
||||
@change:offset="handleOffset"
|
||||
:events="events"
|
||||
:initial-mode="propsViewData.mode"
|
||||
show-weeks
|
||||
@select:day="selectDay"
|
||||
@change:mode="handleChangeMode"
|
||||
v-model:minimized="minimized"
|
||||
>
|
||||
<template #calendarDownloads>
|
||||
<div v-for="{title,icon,link} in downloadLinks">
|
||||
<a :href="link" :title="title" class="py-1 px-2 m-1 btn btn-outline-secondary">
|
||||
@@ -240,7 +355,7 @@ export const Stundenplan = {
|
||||
<span class="flex-grow-1 text-center ">{{event.topic}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="p-1">
|
||||
<div v-else @click="showModal($event, event)" class="p-1">
|
||||
<span>{{event.topic}}</span>
|
||||
</div>
|
||||
</template>
|
||||
@@ -282,17 +397,17 @@ export const Stundenplan = {
|
||||
<span class="small">{{convertTime(event.ende.split(":"))}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col ">
|
||||
<p>Lehrveranstaltung:</p>
|
||||
<p class="m-0">{{event?.topic}}</p>
|
||||
<div class="col">
|
||||
<p>{{ $p.t('lehre/lehrveranstaltung') }}:</p>
|
||||
<p class="m-0">{{event?.orig.topic}}</p>
|
||||
</div>
|
||||
<div class="col ">
|
||||
<p>Lektor:</p>
|
||||
<p class="m-0" v-for="lektor in event?.lektor">{{lektor.kurzbz}}</p>
|
||||
<div class="col" :style="'max-height: ' + eventMaxHeight + '; overflow: auto;'">
|
||||
<p>{{ $p.t('lehre/lektor') }}:</p>
|
||||
<p class="m-0" v-for="lektor in event?.orig.lektor">{{lektor.kurzbz}}</p>
|
||||
</div>
|
||||
<div class="col ">
|
||||
<p>Ort: </p>
|
||||
<p class="m-0">{{event?.ort_kurzbz}}</p>
|
||||
<div class="col">
|
||||
<p>{{ $p.t('profil/Ort') }}: </p>
|
||||
<p class="m-0">{{event?.orig.ort_kurzbz}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -304,12 +419,14 @@ export const Stundenplan = {
|
||||
<lv-info :event="event" />
|
||||
</div>
|
||||
<template v-if="event.type != 'moodle'">
|
||||
<h3 >Lehrveranstaltungs Menu</h3>
|
||||
<h3 >{{$p.t('lehre','lehrveranstaltungsmenue')}}</h3>
|
||||
<lv-menu :containerStyles="['p-0']" :rowStyles="['m-0']" v-show="lvMenu" :menu="lvMenu" />
|
||||
</template>
|
||||
</template>
|
||||
</fhc-calendar>
|
||||
`
|
||||
<template #pageMobilContentEmpty >
|
||||
<h3>{{ $p.t('lehre/noLvFound') }}</h3>
|
||||
</template>
|
||||
</fhc-calendar>`
|
||||
}
|
||||
|
||||
export default Stundenplan
|
||||
@@ -265,11 +265,11 @@ export default {
|
||||
|
||||
</div>
|
||||
<div v-if="!value.length" class="list-group-item small text-center">
|
||||
{{ p.t('lehre/noLvFound') }}
|
||||
{{ $p.t('lehre/noLvFound') }}
|
||||
</div>
|
||||
</template>
|
||||
<div v-else class="d-flex h-100 justify-content-center align-items-center fst-italic text-center">
|
||||
{{ p.t('lehre/noLvFound') }}
|
||||
{{ $p.t('lehre/noLvFound') }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -159,11 +159,11 @@ export default {
|
||||
template: /*html*/ `
|
||||
<div class="widgets-url w-100 h-100 overflow-scroll" style="padding: 1rem 1rem;">
|
||||
<div class="d-flex flex-column justify-content-between">
|
||||
<!-- todo: widgetTag ?? -->
|
||||
<button v-if="editModeIsActive" class="btn btn-outline-secondary btn-sm w-100 mt-2" @click="openCreateModal" type="button">{{$p.t('bookmark','newLink')}}</button>
|
||||
|
||||
<template v-if="shared">
|
||||
|
||||
<template v-if="!emptyBookmarks">
|
||||
<button v-if="editModeIsActive" class="btn btn-outline-secondary btn-sm w-100 mt-2" @click="openCreateModal" type="button">{{$p.t('bookmark','newLink')}}</button>
|
||||
<div v-for="link in shared" :key="link.id" class="d-flex mt-2">
|
||||
<a target="_blank" :href="link.url">
|
||||
<i class="fa fa-solid fa-arrow-up-right-from-square me-1"></i>{{ link.title }}
|
||||
@@ -208,7 +208,7 @@ export default {
|
||||
<form-input id="editUrl" v-model="url_input" name="url"></form-input>
|
||||
</template>
|
||||
<template #footer>
|
||||
<button @click="editBookmark" class="btn btn-primary">{{$p.t('bookmark','editLink')}}</button>
|
||||
<button @click="editBookmark" class="btn btn-primary">{{$p.t('bookmark','saveLink')}}</button>
|
||||
</template>
|
||||
</bs-modal>
|
||||
</core-form>
|
||||
|
||||
@@ -71,9 +71,9 @@ class CalendarDate {
|
||||
}
|
||||
get wYear() {
|
||||
if( this.w === 1 ) {
|
||||
return this.cdLastDayOfWeek.format({ year: 'numeric' });
|
||||
return this.cdLastDayOfWeek.y;
|
||||
}
|
||||
return this.cdFirstDayOfWeek.format({ year: 'numeric' });
|
||||
return this.cdFirstDayOfWeek.y;
|
||||
}
|
||||
get wd() {
|
||||
if (this._wd === null) {
|
||||
@@ -271,4 +271,4 @@ CalendarDate.getWeekStart = function(locale) {
|
||||
}
|
||||
}
|
||||
|
||||
export default CalendarDate
|
||||
export default CalendarDate
|
||||
|
||||
@@ -20184,6 +20184,46 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'rauminfo',
|
||||
'phrase' => 'rauminfo',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Raum Informationen",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "Room Information",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'rauminfo',
|
||||
'phrase' => 'keineRaumReservierung',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Keine Raum Reservierungen gefunden",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "No Room Reservations found",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'lehre',
|
||||
@@ -37257,6 +37297,46 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'lehre',
|
||||
'phrase' => 'lehrveranstaltungsmenue',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Lehrveranstaltungsmenü',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Course Menu',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'lehre',
|
||||
'phrase' => 'lehrveranstaltungsmenueUnavailable',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Kein Lehrveranstaltungsmenü verfügbar',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'No Course Menu available',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'lehre',
|
||||
|
||||
Reference in New Issue
Block a user