mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-26 09:04:28 +00:00
Implementation CIS => LvPlanWidget
This commit is contained in:
@@ -17,6 +17,9 @@ class Cis4 extends Auth_Controller
|
|||||||
'index' => 'basis/cis:r'
|
'index' => 'basis/cis:r'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Load Config
|
||||||
|
$this->load->config('calendar');
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------
|
||||||
@@ -27,15 +30,16 @@ class Cis4 extends Auth_Controller
|
|||||||
*/
|
*/
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$this->load->model('person/Person_model','PersonModel');
|
$this->load->model('person/Person_model', 'PersonModel');
|
||||||
$personData = getData($this->PersonModel->getByUid(getAuthUID()))[0];
|
$personData = getData($this->PersonModel->getByUid(getAuthUID()))[0];
|
||||||
|
|
||||||
$viewData = array(
|
$viewData = array(
|
||||||
'uid' => getAuthUID(),
|
'uid' => getAuthUID(),
|
||||||
'name' => $personData->vorname,
|
'name' => $personData->vorname,
|
||||||
'person_id' => $personData->person_id
|
'person_id' => $personData->person_id,
|
||||||
|
'timezone' => $this->config->item('timezone')
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->load->view('CisRouterView/CisRouterView.php',['viewData' => $viewData, 'route' => 'FhcDashboard']);
|
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'FhcDashboard']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,27 +124,27 @@
|
|||||||
|
|
||||||
.dayPageContainer .feiertagEventContent #ferienEventTitle {}
|
.dayPageContainer .feiertagEventContent #ferienEventTitle {}
|
||||||
|
|
||||||
/* Minimized Container Styles */
|
/* List Page Container Styles */
|
||||||
|
|
||||||
/* Ferientage Events for Minimized */
|
/* Ferientage Events for List Page */
|
||||||
|
|
||||||
.minimizedContainer .feiertagEventContent{
|
.listPageContainer .feiertagEventContent{
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: var(--fhc-light);
|
color: var(--fhc-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.minimizedContainer .feiertagEventContent #ferienEventIcon{
|
.listPageContainer .feiertagEventContent #ferienEventIcon{
|
||||||
margin: 0.5rem;
|
margin: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.minimizedContainer .feiertagEventContent #ferienEventTitle{
|
.listPageContainer .feiertagEventContent #ferienEventTitle{
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lehreinheits Events in Minimized */
|
/* Lehreinheits Events in List Page */
|
||||||
.dayPageContainer .lehreinheitEventContent {
|
.listPageContainer .lehreinheitEventContent {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-left: 4rem;
|
padding-left: 4rem;
|
||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
@@ -152,15 +152,43 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dayPageContainer .lehreinheitEventContent #lehreinheitEventHeader {
|
.listPageContainer .lehreinheitEventContent #lehreinheitEventHeader {
|
||||||
display: grid;
|
display: grid;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dayPageContainer .lehreinheitEventContent #lehreinheitEventText {
|
.listPageContainer .lehreinheitEventContent #lehreinheitEventText {
|
||||||
display: contents;
|
display: contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dayPageContainer .lehreinheitEventContent #lehreinheitEventText * {
|
.listPageContainer .lehreinheitEventContent #lehreinheitEventText * {
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Widget Styles */
|
||||||
|
.dashboard-widget-lvplan .fhc-calendar-base .card {
|
||||||
|
--bs-card-cap-padding-x: 0;
|
||||||
|
--bs-card-cap-padding-y: 0;
|
||||||
|
--bs-card-border-radius: 0;
|
||||||
|
--bs-card-border-width: 0;
|
||||||
|
--dp-input-padding: .375rem .75rem;
|
||||||
|
--dp-input-icon-padding: calc(1rem + 24px);
|
||||||
|
}
|
||||||
|
.dashboard-widget-lvplan .fhc-calendar-base .card-header {
|
||||||
|
border-bottom-width: var(--bs-border-width);
|
||||||
|
}
|
||||||
|
.dashboard-widget-lvplan .fhc-calendar-base .card-header > .row > .col-auto,
|
||||||
|
.dashboard-widget-lvplan .fhc-calendar-base .card-header .btn-group {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.dashboard-widget-lvplan .fhc-calendar-base .card-header input {
|
||||||
|
--dp-font-size: .7em;
|
||||||
|
}
|
||||||
|
.dashboard-widget-lvplan .fhc-calendar-base .card-header .btn {
|
||||||
|
--bs-btn-font-size: .7em;
|
||||||
|
}
|
||||||
|
.dashboard-widget-lvplan .fhc-calendar-base-label-day {
|
||||||
|
cursor: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
.fhc-calendar-base-grid-line-event {
|
.event {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.fhc-calendar-mode-week .all-day-events .fhc-calendar-base-grid-line-event .weekPageContainer {
|
.fhc-calendar-mode-week .all-day-events .fhc-calendar-base-grid-line-event .weekPageContainer {
|
||||||
@@ -59,9 +59,9 @@
|
|||||||
.fhc-calendar-base-grid-line-event .event-type-reservierung {
|
.fhc-calendar-base-grid-line-event .event-type-reservierung {
|
||||||
--event-default-bg: var(--fhc-calendar-bg-reservierung, #fff);
|
--event-default-bg: var(--fhc-calendar-bg-reservierung, #fff);
|
||||||
}
|
}
|
||||||
.fhc-calendar-base-grid-line-event > * {
|
.fhc-calendar-base .event > * {
|
||||||
background-color: var(--event-bg, var(--event-default-bg));
|
background-color: var(--event-bg, var(--event-default-bg));
|
||||||
}
|
}
|
||||||
.fhc-calendar-base-grid-line-event > *:hover {
|
.fhc-calendar-base .event > *:hover {
|
||||||
filter: brightness(120%);
|
filter: brightness(120%);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,6 +264,7 @@ export default {
|
|||||||
:btn-week="!!modes['week'] && (btnWeek || (showBtns && btnWeek !== false))"
|
:btn-week="!!modes['week'] && (btnWeek || (showBtns && btnWeek !== false))"
|
||||||
:btn-month="!!modes['month'] && (btnMonth || (showBtns && btnMonth !== false))"
|
:btn-month="!!modes['month'] && (btnMonth || (showBtns && btnMonth !== false))"
|
||||||
:btn-list="!!modes['list'] && (btnList || (showBtns && btnList !== false))"
|
:btn-list="!!modes['list'] && (btnList || (showBtns && btnList !== false))"
|
||||||
|
:mode-options="modeOptions ? modeOptions[cMode] : undefined"
|
||||||
>
|
>
|
||||||
<slot name="actions" />
|
<slot name="actions" />
|
||||||
</base-header>
|
</base-header>
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default {
|
|||||||
},
|
},
|
||||||
template: /* html */`
|
template: /* html */`
|
||||||
<div
|
<div
|
||||||
class="fhc-calendar-base-grid-line-event"
|
class="fhc-calendar-base-grid-line-event event"
|
||||||
:class="classes"
|
:class="classes"
|
||||||
style="z-index: 1"
|
style="z-index: 1"
|
||||||
:draggable="draggable"
|
:draggable="draggable"
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
modeOptions: {
|
||||||
|
type: Object,
|
||||||
|
default: {}
|
||||||
|
},
|
||||||
btnMonth: Boolean,
|
btnMonth: Boolean,
|
||||||
btnWeek: Boolean,
|
btnWeek: Boolean,
|
||||||
btnDay: Boolean,
|
btnDay: Boolean,
|
||||||
@@ -62,6 +66,7 @@ export default {
|
|||||||
@update:date="$emit('update:date', $event)"
|
@update:date="$emit('update:date', $event)"
|
||||||
@open="open = true"
|
@open="open = true"
|
||||||
@closed="open = false"
|
@closed="open = false"
|
||||||
|
:list-length="modeOptions.length"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
class="btn btn-outline-secondary border-0"
|
class="btn btn-outline-secondary border-0"
|
||||||
|
|||||||
@@ -51,20 +51,17 @@ export default {
|
|||||||
case "month":
|
case "month":
|
||||||
return this.date.toLocaleString({ month: 'long', year: 'numeric' });
|
return this.date.toLocaleString({ month: 'long', year: 'numeric' });
|
||||||
case "week":
|
case "week":
|
||||||
const year = this.date.localWeekYear;
|
var year = this.date.localWeekYear;
|
||||||
const week = this.date.toFormat('nn');
|
var week = this.date.toFormat('nn');
|
||||||
return this.$p.t('calendar/year_kw', { year, week });
|
return this.$p.t('calendar/year_kw', { year, week });
|
||||||
case "list":
|
case "list":
|
||||||
|
return this.date.toLocaleString(luxon.DateTime.DATE_FULL) + '-' + this.date.plus({ days: this.listLength - 1 }).toLocaleString(luxon.DateTime.DATE_FULL);
|
||||||
case "day":
|
case "day":
|
||||||
return this.date.toLocaleString(luxon.DateTime.DATE_FULL);
|
return this.date.toLocaleString(luxon.DateTime.DATE_FULL);
|
||||||
default:
|
default:
|
||||||
return 'View not Supported';
|
return 'View not Supported';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
format() {
|
|
||||||
const title = this.title;
|
|
||||||
return `'${title}'`;
|
|
||||||
},
|
|
||||||
weekStart() {
|
weekStart() {
|
||||||
return luxon.Info.getStartOfWeek(this.date)%7;
|
return luxon.Info.getStartOfWeek(this.date)%7;
|
||||||
}
|
}
|
||||||
@@ -97,10 +94,10 @@ export default {
|
|||||||
<vue-date-picker
|
<vue-date-picker
|
||||||
:model-value="current"
|
:model-value="current"
|
||||||
@update:model-value="update"
|
@update:model-value="update"
|
||||||
:format="format"
|
:format="() => title"
|
||||||
:month-picker="mode == 'month'"
|
:month-picker="mode == 'month'"
|
||||||
:week-picker="mode == 'week'"
|
:week-picker="mode == 'week'"
|
||||||
:range="mode == 'list' ? { autoRange: listLength } : false"
|
:range="mode == 'list' ? { autoRange: listLength - 1 } : false"
|
||||||
:text-input="mode == 'day'"
|
:text-input="mode == 'day'"
|
||||||
:week-start="weekStart"
|
:week-start="weekStart"
|
||||||
:week-numbers="{ type: weekNumbers }"
|
:week-numbers="{ type: weekNumbers }"
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ export default {
|
|||||||
emits: [
|
emits: [
|
||||||
"update:currentDate",
|
"update:currentDate",
|
||||||
"update:range",
|
"update:range",
|
||||||
"click"
|
"click",
|
||||||
|
"requestModalOpen"
|
||||||
],
|
],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -35,9 +36,9 @@ export default {
|
|||||||
|
|
||||||
if (this.rangeOffset != 0) {
|
if (this.rangeOffset != 0) {
|
||||||
if (this.rangeOffset < 0) {
|
if (this.rangeOffset < 0) {
|
||||||
first = first.plus({ days: this.rangeOffset * this.length });
|
first = first.plus({ days: this.rangeOffset });
|
||||||
} else {
|
} else {
|
||||||
last = last.plus({ days: this.rangeOffset * this.length });
|
last = first.plus({ days: this.rangeOffset + this.length });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ export default {
|
|||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
currentDate() {
|
currentDate() {
|
||||||
this.rangeOffset = Math.floor(this.currentDate.startOf('day').diff(this.focusDate.startOf('day'), 'days').days / this.length);
|
this.rangeOffset = this.currentDate.startOf('day').diff(this.focusDate.startOf('day'), 'days').days;
|
||||||
if (this.rangeOffset) {
|
if (this.rangeOffset) {
|
||||||
this.$emit('update:range', this.range);
|
this.$emit('update:range', this.range);
|
||||||
this.$refs.slider.slidePages(this.rangeOffset).then(this.updatePage);
|
this.$refs.slider.slidePages(this.rangeOffset).then(this.updatePage);
|
||||||
@@ -65,15 +66,23 @@ export default {
|
|||||||
this.$refs.slider.nextPage().then(this.updatePage);
|
this.$refs.slider.nextPage().then(this.updatePage);
|
||||||
},
|
},
|
||||||
updatePage(offset) {
|
updatePage(offset) {
|
||||||
const newFocusDate = this.focusDate.plus({ days: offset * this.length });
|
const newFocusDate = this.focusDate.plus({ days: offset });
|
||||||
this.focusDate = newFocusDate;
|
this.focusDate = newFocusDate;
|
||||||
this.rangeOffset = 0;
|
this.rangeOffset = 0;
|
||||||
this.$emit('update:currentDate', this.focusDate);
|
this.$emit('update:currentDate', this.focusDate);
|
||||||
this.$emit('update:range', this.range);
|
this.$emit('update:range', this.range);
|
||||||
},
|
},
|
||||||
viewAttrs(offset) {
|
viewAttrs(offset) {
|
||||||
const day = this.focusDate.plus({ days: offset * this.length });
|
const day = this.focusDate.plus({ days: offset });
|
||||||
return { day, length: this.length };
|
return { day, length: this.length };
|
||||||
|
},
|
||||||
|
handleClickDefaults(evt) {
|
||||||
|
switch (evt.detail.source) {
|
||||||
|
case 'event':
|
||||||
|
// default: Request Modal
|
||||||
|
this.$emit('requestModalOpen', { event: evt.detail.value });
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -82,6 +91,7 @@ export default {
|
|||||||
template: `
|
template: `
|
||||||
<div
|
<div
|
||||||
class="fhc-calendar-mode-list flex-grow-1 position-relative"
|
class="fhc-calendar-mode-list flex-grow-1 position-relative"
|
||||||
|
@cal-click-default.capture="handleClickDefaults"
|
||||||
>
|
>
|
||||||
<base-slider ref="slider" v-slot="slot">
|
<base-slider ref="slider" v-slot="slot">
|
||||||
<list-view v-bind="viewAttrs(slot.offset)">
|
<list-view v-bind="viewAttrs(slot.offset)">
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import LabelDay from '../../Base/Label/Day.js';
|
import LabelDay from '../../Base/Label/Day.js';
|
||||||
import LabelDow from '../../Base/Label/Dow.js';
|
import LabelDow from '../../Base/Label/Dow.js';
|
||||||
|
|
||||||
|
import CalDnd from '../../../../directives/Calendar/DragAndDrop.js';
|
||||||
|
import CalClick from '../../../../directives/Calendar/Click.js';
|
||||||
|
|
||||||
// TODO(chris): drag and drop
|
// TODO(chris): drag and drop
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -9,7 +12,12 @@ export default {
|
|||||||
LabelDay,
|
LabelDay,
|
||||||
LabelDow
|
LabelDow
|
||||||
},
|
},
|
||||||
|
directives: {
|
||||||
|
CalDnd,
|
||||||
|
CalClick
|
||||||
|
},
|
||||||
inject: {
|
inject: {
|
||||||
|
draggableEvents: "draggableEvents",
|
||||||
events: "events"
|
events: "events"
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
@@ -43,20 +51,31 @@ export default {
|
|||||||
return eventsPerDay.filter(day => day.events.length);
|
return eventsPerDay.filter(day => day.events.length);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
draggable(event) {
|
||||||
|
return this.draggableEvents(event.orig, 'list');
|
||||||
|
},
|
||||||
|
},
|
||||||
template: /* html */`
|
template: /* html */`
|
||||||
<div
|
<div class="fhc-calendar-mode-list-view h-100 overflow-auto">
|
||||||
class="fhc-calendar-mode-list-view h-100"
|
<div v-if="!eventsPerDay.length" class="h-100">
|
||||||
>
|
|
||||||
<div v-if="!eventsPerDay.length">
|
|
||||||
<slot :event="undefined" mode="list" />
|
<slot :event="undefined" mode="list" />
|
||||||
</div>
|
</div>
|
||||||
<div v-for="{ day, events } in eventsPerDay" class="text-center">
|
<div v-for="{ day, events } in eventsPerDay" class="text-center">
|
||||||
<label-dow :date="day" class="d-inline" />, <label-day :date="day" class="d-inline" />
|
<label-dow :date="day" class="d-inline" />, <label-day :date="day" class="d-inline" />
|
||||||
<div v-for="event in events">
|
<div v-for="event in events">
|
||||||
<div v-if="slot.event.type == 'loading'" class="placeholder-glow opacity-50">
|
<div v-if="event.type == 'loading'" class="placeholder-glow opacity-50">
|
||||||
<span class="placeholder w-100" />
|
<span class="placeholder w-100" />
|
||||||
</div>
|
</div>
|
||||||
<slot v-else :event="event.orig" mode="list" />
|
<div
|
||||||
|
v-else
|
||||||
|
class="event"
|
||||||
|
:draggable="draggable(event)"
|
||||||
|
v-cal-dnd:draggable="event"
|
||||||
|
v-cal-click:event="event.orig"
|
||||||
|
>
|
||||||
|
<slot :event="event.orig" mode="list" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,9 +19,8 @@ export default {
|
|||||||
viewData: {
|
viewData: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
default: () => ({name: '', uid: ''}),
|
|
||||||
validator(value) {
|
validator(value) {
|
||||||
return value && value.name && value.uid
|
return value && value.name && value.uid && value.timezone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -37,6 +36,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
editMode: Vue.computed(()=>this.editMode),
|
editMode: Vue.computed(()=>this.editMode),
|
||||||
widgetsSetup: Vue.computed(() => this.widgets),
|
widgetsSetup: Vue.computed(() => this.widgets),
|
||||||
|
timezone: Vue.computed(() => this.viewData.timezone)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|||||||
@@ -1,266 +1,115 @@
|
|||||||
import Phrasen from '../../mixins/Phrasen.js';
|
|
||||||
import AbstractWidget from './Abstract.js';
|
import AbstractWidget from './Abstract.js';
|
||||||
import FhcCalendar from '../Calendar/Calendar.js';
|
import FhcCalendar from '../Calendar/Base.js';
|
||||||
import LvModal from '../Cis/Mylv/LvModal.js';
|
|
||||||
import ContentModal from '../Cis/Cms/ContentModal.js'
|
|
||||||
import CalendarDate from '../../composables/CalendarDate.js';
|
|
||||||
|
|
||||||
import ApiLvPlan from '../../api/factory/lvPlan.js';
|
import ApiLvPlan from '../../api/factory/lvPlan.js';
|
||||||
import ApiOrt from '../../api/factory/ort.js';
|
|
||||||
|
import { useEventLoader } from '../../composables/EventLoader.js';
|
||||||
|
|
||||||
|
import ModeList from '../Calendar/Mode/List.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "LvPlanWidget",
|
name: "LvPlanWidget",
|
||||||
|
components: {
|
||||||
|
FhcCalendar
|
||||||
|
},
|
||||||
mixins: [
|
mixins: [
|
||||||
Phrasen,
|
|
||||||
AbstractWidget
|
AbstractWidget
|
||||||
],
|
],
|
||||||
components: {
|
inject: [
|
||||||
FhcCalendar,
|
"renderers",
|
||||||
LvModal,
|
"timezone"
|
||||||
ContentModal
|
],
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
stunden: [],
|
now: luxon.DateTime.now().setZone(this.timezone),
|
||||||
minimized: true,
|
modes: {
|
||||||
events: null,
|
list: Vue.markRaw(ModeList)
|
||||||
currentDay: this.getCurrentDate(),
|
},
|
||||||
calendarDate: new CalendarDate(new Date()),
|
modeOptions: {
|
||||||
roomInfoContentID: null,
|
list: {
|
||||||
ort_kurzbz: null,
|
length: 7
|
||||||
selectedEvent: null,
|
|
||||||
isModalContentResolved: false,
|
|
||||||
isModalTitleResolved: false,
|
|
||||||
isShowModal: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
inject: ["renderers"],
|
|
||||||
watch:{
|
|
||||||
modalLoaded: {
|
|
||||||
handler: function (newValue) {
|
|
||||||
if (this.isShowModal && newValue.isModalContentResolved && newValue.isModalTitleResolved) {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.$refs.lvmodal) this.$refs.lvmodal.show();
|
|
||||||
this.isShowModal = false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
immediate: true
|
currentDay: luxon.DateTime.now().setZone(this.timezone).startOf('day')
|
||||||
},
|
}
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
modalLoaded: function () {
|
|
||||||
return { isModalContentResolved: this.isModalContentResolved, isModalTitleResolved: this.isModalTitleResolved };
|
|
||||||
},
|
|
||||||
allEventsGrouped() {
|
|
||||||
// groups all events of the next 7 days together
|
|
||||||
const currentCalendarDate = new CalendarDate(this.currentDay)
|
|
||||||
const mapArr = currentCalendarDate.nextSevenDays.map((d) => [new CalendarDate(d), []])
|
|
||||||
|
|
||||||
// return map of key => calendar date of next 7 days & values the respective events on that date
|
|
||||||
return new Map((this.events || []).filter(evt => evt.start >= this.currentDay).reduce((acc, cur) => {
|
|
||||||
const date = new CalendarDate(new Date(cur.datum))
|
|
||||||
const arr = acc.find(el => el[0].compare(date))
|
|
||||||
if(!arr) return acc
|
|
||||||
arr[1].push(cur)
|
|
||||||
|
|
||||||
return acc
|
|
||||||
}, mapArr));
|
|
||||||
},
|
|
||||||
currentEvents() {
|
|
||||||
return (this.events || []).filter(evt => evt.end < this.dayAfterCurrentDay && evt.start >= this.currentDay);
|
|
||||||
},
|
|
||||||
dayAfterCurrentDay() {
|
|
||||||
let currentDay = new Date(this.currentDay);
|
|
||||||
currentDay.setDate(currentDay.getDate() + 1);
|
|
||||||
return currentDay;
|
|
||||||
},
|
|
||||||
monthFirstDay: function () {
|
|
||||||
return this.calendarDateToString(this.calendarDate.cdFirstDayOfCalendarMonth);
|
|
||||||
},
|
|
||||||
monthLastDay: function () {
|
|
||||||
return this.calendarDateToString(this.calendarDate.cdLastDayOfNextCalendarMonth);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
showModal: function (event) {
|
eventStyle(event) {
|
||||||
this.currentlySelectedEvent = event;
|
const styles = {};
|
||||||
Vue.nextTick(() => {
|
if (event.farbe)
|
||||||
if (this.isModalContentResolved && this.isModalTitleResolved) {
|
styles['--event-bg'] = '#' + event.farbe;
|
||||||
if (this.$refs.lvmodal) this.$refs.lvmodal.show();
|
else if (event.type == 'reservierung')
|
||||||
}
|
styles['--event-bg'] = '#ffffff';
|
||||||
else {
|
else
|
||||||
this.isShowModal = true;
|
styles['--event-bg'] = '#cccccc';
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
modalTitleResolved: function () {
|
|
||||||
this.isModalTitleResolved = true;
|
|
||||||
|
|
||||||
},
|
|
||||||
modalContentResolved: function () {
|
|
||||||
this.isModalContentResolved = true;
|
|
||||||
|
|
||||||
},
|
|
||||||
modalTitleComponent(type) {
|
|
||||||
return this.renderers[type]?.modalTitle;
|
|
||||||
},
|
|
||||||
modalContentComponent(type) {
|
|
||||||
return this.renderers[type]?.modalContent;
|
|
||||||
},
|
|
||||||
calendarEventComponent(type) {
|
|
||||||
return this.renderers[type]?.calendarEvent;
|
|
||||||
},
|
|
||||||
getEventStyle: function(evt) {
|
|
||||||
const styles = {'background-color': evt.color};
|
|
||||||
if(evt.start.getTime() < Date.now()) styles.opacity = 0.5;
|
|
||||||
|
|
||||||
|
const eventEnd = luxon.DateTime.fromISO(event.isoend, { zone: this.timezone });
|
||||||
|
if (eventEnd < this.now)
|
||||||
|
styles['opacity'] = .5;
|
||||||
|
|
||||||
return styles;
|
return styles;
|
||||||
},
|
},
|
||||||
getCurrentDate: function() {
|
updateRange(rangeInterval) {
|
||||||
const today = new Date()
|
this.rangeInterval = rangeInterval;
|
||||||
today.setHours(0,0,0)
|
|
||||||
return today
|
|
||||||
},
|
|
||||||
calendarDateToString: function (calendarDate) {
|
|
||||||
|
|
||||||
return calendarDate instanceof CalendarDate ?
|
|
||||||
[calendarDate.y, calendarDate.m + 1, calendarDate.d].join('-') :
|
|
||||||
null;
|
|
||||||
|
|
||||||
},
|
|
||||||
showRoomInfoModal: function(ort_kurzbz){
|
|
||||||
// getting the content_id of the ort_kurzbz
|
|
||||||
this.$api
|
|
||||||
.call(ApiOrt.getContentID(ort_kurzbz))
|
|
||||||
.then(res => {
|
|
||||||
this.roomInfoContentID = res.data;
|
|
||||||
this.ort_kurzbz = ort_kurzbz;
|
|
||||||
|
|
||||||
// only showing the modal after vue was able to set the reactive data
|
|
||||||
Vue.nextTick(() => { this.$refs.contentModal.show(); });
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.err(err);
|
|
||||||
this.ort_kurzbz = null;
|
|
||||||
this.roomInfoContentID = null;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
showLvUebersicht: function (event){
|
|
||||||
this.selectedEvent= event;
|
|
||||||
Vue.nextTick(()=>{
|
|
||||||
this.$refs.lvmodal.show();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
selectDay(day) {
|
|
||||||
this.currentDay = day;
|
|
||||||
this.minimized = true;
|
|
||||||
},
|
|
||||||
|
|
||||||
updateRange: function (data) {
|
|
||||||
|
|
||||||
let tmp_date = new CalendarDate(data.start);
|
|
||||||
// only load month data if the month or year has changed
|
|
||||||
if (tmp_date.m != this.calendarDate.m || tmp_date.y != this.calendarDate.y) {
|
|
||||||
this.calendarDate = tmp_date;
|
|
||||||
Vue.nextTick(() => {
|
|
||||||
this.loadEvents();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
loadEvents: function () {
|
|
||||||
Promise.allSettled([
|
|
||||||
this.$api.call(ApiLvPlan.LvPlanEvents(this.monthFirstDay, this.monthLastDay)),
|
|
||||||
this.$api.call(ApiLvPlan.getLvPlanReservierungen(this.monthFirstDay, this.monthLastDay))
|
|
||||||
]).then((result) => {
|
|
||||||
let promise_events = [];
|
|
||||||
result.forEach((promise_result) => {
|
|
||||||
if (promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success") {
|
|
||||||
|
|
||||||
let data = promise_result.value.data;
|
|
||||||
// adding additional information to the events
|
|
||||||
if (data && data.forEach) {
|
|
||||||
|
|
||||||
data.forEach((el, i) => {
|
|
||||||
el.id = i;
|
|
||||||
if (el.type === 'reservierung') {
|
|
||||||
el.color = '#' + (el.farbe || 'FFFFFF');
|
|
||||||
} else {
|
|
||||||
el.color = '#' + (el.farbe || 'CCCCCC');
|
|
||||||
}
|
|
||||||
|
|
||||||
el.start = new Date(el.datum + ' ' + el.beginn);
|
|
||||||
el.end = new Date(el.datum + ' ' + el.ende);
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
promise_events = promise_events.concat(data);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
this.events = promise_events;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
setCalendarMaximized() {
|
|
||||||
this.minimized = false
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const $api = Vue.inject('$api');
|
||||||
|
|
||||||
|
const rangeInterval = Vue.ref(null);
|
||||||
|
|
||||||
|
const { events } = useEventLoader(rangeInterval, (start, end) => {
|
||||||
|
return [
|
||||||
|
$api.call(ApiLvPlan.LvPlanEvents(start.toISODate(), end.toISODate())),
|
||||||
|
$api.call(ApiLvPlan.getLvPlanReservierungen(start.toISODate(), end.toISODate()))
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
rangeInterval,
|
||||||
|
events
|
||||||
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$emit('setConfig', false);
|
this.$emit('setConfig', false);
|
||||||
this.loadEvents();
|
|
||||||
},
|
},
|
||||||
template: /*html*/`
|
template: /*html*/`
|
||||||
<div class="dashboard-widget-lvplan d-flex flex-column h-100">
|
<div class="dashboard-widget-lvplan d-flex flex-column h-100">
|
||||||
<lv-modal v-if="selectedEvent" ref="lvmodal" :event="selectedEvent" >
|
<fhc-calendar
|
||||||
<template #modalTitle>
|
v-model:date="currentDay"
|
||||||
<Suspense @pending="isModalTitleResolved=false" @resolve="modalTitleResolved">
|
:modes="modes"
|
||||||
<component :is="modalTitleComponent(selectedEvent.type)" v-if="selectedEvent" :event="selectedEvent" ></component>
|
:mode-options="modeOptions"
|
||||||
</Suspense>
|
@update:range="updateRange"
|
||||||
</template>
|
:timezone="timezone"
|
||||||
<template #modalContent>
|
:locale="$p.user_locale.value"
|
||||||
<Suspense @pending="isModalContentResolved=false" @resolve="modalContentResolved">
|
:events="events"
|
||||||
<component :is="modalContentComponent(selectedEvent.type)" v-if="selectedEvent" :event="selectedEvent" ></component>
|
>
|
||||||
</Suspense>
|
<template v-slot="{ event, mode }">
|
||||||
</template>
|
<div
|
||||||
</lv-modal>
|
v-if="!event"
|
||||||
<content-modal :content_id="roomInfoContentID" dialogClass="modal-lg" ref="contentModal"/>
|
class="h-100 d-flex justify-content-center align-items-center"
|
||||||
<fhc-calendar @change:range="updateRange" :initial-date="currentDay" class="border-0" class-header="p-0" @select:day="selectDay" :widget="true" v-model:minimized="minimized" :events="events" no-week-view :show-weeks="false" >
|
>
|
||||||
<template #monthPage="{event,day}">
|
{{ $p.t('lehre/noLvFound') }}
|
||||||
<div v-if="event.type=='moodle'">
|
|
||||||
<div class="d-flex small w-100" >
|
|
||||||
<moodle-svg></moodle-svg>
|
|
||||||
<span v-contrast class="flex-grow-1 text-center "><strong v-html="event.titel"></strong> - {{event.topic}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<span v-else class="small" >
|
<component
|
||||||
{{event.topic}}
|
v-else-if="mode == 'eventheader'"
|
||||||
</span>
|
:is="renderers[event.type]?.modalTitle"
|
||||||
</template>
|
:event="event"
|
||||||
<template #minimizedPage >
|
></component>
|
||||||
<div class="minimizedContainer flex-grow-1" style="overflow-y: auto; overflow-x: hidden">
|
<component
|
||||||
<div v-if="events === null" class="d-flex h-100 justify-content-center align-items-center">
|
v-else-if="mode == 'event'"
|
||||||
<i class="fa-solid fa-spinner fa-pulse fa-3x"></i>
|
:is="renderers[event.type]?.modalContent"
|
||||||
</div>
|
:event="event"
|
||||||
<template v-else-if="allEventsGrouped.size" v-for="([key, value], index) in allEventsGrouped" :key="index" style="margin-top: 8px;">
|
></component>
|
||||||
<div class=" card-header d-grid p-0">
|
<div
|
||||||
<button class="btn fhc-tertiary text-decoration-none" @click="setCalendarMaximized">{{ key.format({dateStyle: "full"}, $p.user_locale.value)}}</button>
|
v-else
|
||||||
</div>
|
:class="'event-type-' + event.type + ' ' + mode + 'PageContainer'"
|
||||||
<div role="button" @click="showLvUebersicht(evt)" v-for="evt in value" :key="evt.id" class="list-group-item small" :style="getEventStyle(evt)">
|
:style="eventStyle(event)"
|
||||||
<component :is="calendarEventComponent(evt.type)" :event="evt" ></component>
|
>
|
||||||
</div>
|
<component
|
||||||
<div v-if="!value.length" class="list-group-item small text-center">
|
:is="renderers[event.type]?.calendarEvent"
|
||||||
{{ $p.t('lehre/noLvFound') }}
|
:event="event"
|
||||||
</div>
|
></component>
|
||||||
</template>
|
|
||||||
<div v-else class="d-flex h-100 justify-content-center align-items-center fst-italic text-center">
|
|
||||||
{{ $p.t('lehre/noLvFound') }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</fhc-calendar>
|
</fhc-calendar>
|
||||||
|
|||||||
Reference in New Issue
Block a user