Merge branch 'feature-25999/C4_cleanup' into merge_FHC4_C4

This commit is contained in:
Harald Bamberger
2025-02-19 14:25:04 +01:00
12 changed files with 342 additions and 60 deletions
+11 -1
View File
@@ -61,7 +61,17 @@ $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/null/null/null';
$route['Cis/Stundenplan/(:num)'] = 'Cis/Stundenplan/index/null/null/$1';
$route['Cis/Stundenplan/(:num)/(:any)'] = 'Cis/Stundenplan/index/null/$2/$1';
// Specific route (for mode: month|week|day, focusdate, lv_id optional)
$route['Cis/Stundenplan/([M|m]onth|[W|w]eek|[D|d]ay)'] = 'Cis/Stundenplan/index/$1';
$route['Cis/Stundenplan/([M|m]onth|[W|w]eek|[D|d]ay)(/(:any))?'] = 'Cis/Stundenplan/index/$1/$3';
$route['Cis/Stundenplan/([M|m]onth|[W|w]eek|[D|d]ay)(/(:any))?(/(:num))?'] = 'Cis/Stundenplan/index/$1/$3/$5';
// load routes from extensions
$subdir = 'application/config/extensions';
+10 -1
View File
@@ -23,9 +23,18 @@ class Stundenplan extends Auth_Controller
/**
* @return void
*/
public function index($lv_id = null)
public function index($mode = 'Week', $focus_date = null, $lv_id = null)
{
// convert string "null" to actual null values -> ci3 reroute fix
$mode = ($mode === 'null') ? 'Week' : ucfirst(strtolower($mode));
$focus_date = ($focus_date === 'null') ? date('Y-m-d') : $focus_date;
$lv_id = ($lv_id === 'null') ? null : $lv_id;
if($mode) $mode = ucfirst(strtolower($mode));
$viewData = array(
'mode' => $mode,
'focus_date' => $focus_date,
'lv_id' => $lv_id,
'uid'=>getAuthUID(),
);
+3
View File
@@ -403,6 +403,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
@@ -478,6 +479,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)
);
@@ -492,6 +494,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)
);
+125 -9
View File
@@ -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";
import Stundenplan from "../../components/Cis/Stundenplan/Stundenplan";
import Stundenplan, {DEFAULT_MODE_STUNDENPLAN} from "../../components/Cis/Stundenplan/Stundenplan";
import MylvStudent from "../../components/Cis/Mylv/Student";
import Profil from "../../components/Cis/Profil/Profil";
import CmsNews from "../../components/Cis/Cms/News";
import CmsContent from "../../components/Cis/Cms/Content";
import Info from "../../components/Cis/Mylv/Semester/Studiengang/Lv/Info";
import RoomInformation from "../../components/Cis/Mylv/RoomInformation";
import RoomInformation, {DEFAULT_MODE_RAUMINFO} from "../../components/Cis/Mylv/RoomInformation";
const ciPath = FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, '') + FHC_JS_DATA_STORAGE_OBJECT.ci_router;
@@ -28,11 +28,62 @@ 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: {
ort_kurzbz: to.params.ort_kurzbz
},
};
},
},
{
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 focus_date = 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 +109,67 @@ 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
const focus_date = 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,11 +178,19 @@ 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'
},
};
},
},
]
})
+11 -5
View File
@@ -62,6 +62,9 @@ export default {
noMonthView: Boolean
},
watch:{
mode(newVal) {
this.$emit('change:mode', newVal)
},
selectedEvent:{
handler(newSelectedEvent) {
this.$emit('selectedEvent', newSelectedEvent);
@@ -161,12 +164,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 +190,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,7 +234,6 @@ export default {
}
}).observe(this.$refs.container);
}
},
unmounted(){
CalendarDates.cleanup();
+4 -4
View File
@@ -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>
@@ -273,6 +273,7 @@ export default {
}
},
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) {
@@ -3,13 +3,14 @@ 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
}
},
components: {
FhcCalendar,
@@ -19,9 +20,10 @@ export default{
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 +45,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 +63,36 @@ 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;
},
handleChangeMode(mode) {
const modeCapitalized = mode.charAt(0).toUpperCase() + mode.slice(1)
this.$router.push({
name: "RoomInformation",
params: {
mode: modeCapitalized,
focus_date: this.currentDay.toISOString().split("T")[0],
ort_kurzbz: this.propsViewData.ort_kurzbz
}
})
this.calendarMode = mode
},
showModal: function (event) {
this.currentlySelectedEvent = event;
Vue.nextTick(() => {
@@ -86,8 +126,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 +160,21 @@ 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"
: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 +190,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 +206,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
@@ -177,7 +177,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">
@@ -4,25 +4,28 @@ import LvModal from "../Mylv/LvModal.js";
import LvInfo from "../Mylv/LvInfo.js"
import LvMenu from "../Mylv/LvMenu.js"
export const Stundenplan = {
export const DEFAULT_MODE_STUNDENPLAN = 'Week'
const Stundenplan = {
name: 'Stundenplan',
data() {
return {
events: null,
calendarMode: 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(),
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
},
watch: {
weekFirstDay: {
handler: async function (newValue) {
@@ -33,6 +36,16 @@ 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) {
this.currentDate = new Date(newVal)
}
},
components: {
@@ -49,11 +62,6 @@ export const Stundenplan = {
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
},
weekFirstDay: function () {
return this.calendarDateToString(this.calendarDate.cdFirstDayOfWeek);
},
@@ -66,7 +74,6 @@ export const Stundenplan = {
monthLastDay: function () {
return this.calendarDateToString(this.eventCalendarDate.cdLastDayOfCalendarMonth);
},
},
methods:{
fetchStudiensemesterDetails: async function (date) {
@@ -84,8 +91,35 @@ 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");
this.$router.push({
name: "Stundenplan",
params: {
mode: this.calendarMode,
focus_date: date,
lv_id: this.propsViewData?.lv_id || null
}
})
this.currentDay = day;
},
handleChangeMode(mode) {
const modeCapitalized = mode.charAt(0).toUpperCase() + mode.slice(1)
this.$router.push({
name: "Stundenplan",
params: {
mode: modeCapitalized,
focus_date: this.currentDay.toISOString().split("T")[0],
lv_id: this.propsViewData?.lv_id ?? null
}
})
this.calendarMode = mode
},
showModal: function(event){
this.currentlySelectedEvent = event;
Vue.nextTick(() => {
@@ -117,7 +151,7 @@ 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)
]).then((result) => {
let promise_events = [];
@@ -163,7 +197,18 @@ export const Stundenplan = {
<h2>{{$p.t('lehre/stundenplan')}}</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"
: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">
@@ -230,8 +275,7 @@ export const Stundenplan = {
<template #pageMobilContentEmpty >
<h3>{{ $p.t('lehre/noLvFound') }}</h3>
</template>
</fhc-calendar>
`
</fhc-calendar>`
}
export default Stundenplan
+3 -3
View File
@@ -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>
+40
View File
@@ -20284,6 +20284,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',