Implementation CIS => RoomInformation

This commit is contained in:
chfhtw
2025-07-22 13:14:56 +02:00
parent 0a9f4023b3
commit ad080e61b2
6 changed files with 256 additions and 263 deletions
+7 -2
View File
@@ -87,9 +87,14 @@ class Cms extends Auth_Controller
$this->load->view('CisRouterView/CisRouterView.php', ['viewData'=>$viewData, 'route' => 'News']);
}
public function getRoomInformation($ort_kurzbz){
public function getRoomInformation($ort_kurzbz)
{
// Load Config
$this->load->config('calendar');
$viewData = array(
'ort_kurzbz' => $ort_kurzbz
'ort_kurzbz' => $ort_kurzbz,
'timezone' => $this->config->item('timezone')
);
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'CmsRoom']);
}
@@ -32,7 +32,7 @@ class LvPlan extends FHCAPI_Controller
parent::__construct([
'getRoomplan' => self::PERM_LOGGED,
'Stunden' => self::PERM_LOGGED,
'Reservierungen' => self::PERM_LOGGED,
'getReservierungen' => self::PERM_LOGGED,
'LvPlanEvents' => self::PERM_LOGGED,
'getLehreinheitStudiensemester' => self::PERM_LOGGED,
'studiensemesterDateInterval' => self::PERM_LOGGED,
@@ -181,51 +181,65 @@ class LvPlan extends FHCAPI_Controller
* fetches room events from a certain date
* @access public
*
* @return void
*/
public function getRoomplan()
{
$this->load->library('StundenplanLib');
// form validation
$this->load->library('form_validation');
$this->form_validation->set_data($_GET);
$this->form_validation->set_rules('ort_kurzbz',"Ort","required");
$this->form_validation->set_rules('start_date',"start_date","required");
$this->form_validation->set_rules('end_date',"end_date","required");
if($this->form_validation->run() === FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
// storing the get parameter in local variables
$ort_kurzbz = $this->input->get('ort_kurzbz', TRUE);
$start_date = $this->input->get('start_date', TRUE);
$end_date = $this->input->get('end_date', TRUE);
$this->form_validation->set_rules('ort_kurzbz', "Ort", "required");
$this->form_validation->set_rules('start_date', "start_date", "required");
$this->form_validation->set_rules('end_date', "end_date", "required");
$roomplan_data = $this->LvPlan->lvPlanGruppierung($this->LvPlan->getRoomQuery($ort_kurzbz, $start_date, $end_date));
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
// storing the post parameter in local variables
$ort_kurzbz = $this->input->post('ort_kurzbz', true);
$start_date = $this->input->post('start_date', true);
$end_date = $this->input->post('end_date', true);
// get data
$this->load->library('StundenplanLib');
$roomplan_data = $this->stundenplanlib->getRoomplan($ort_kurzbz, $start_date, $end_date);
$roomplan_data = $this->getDataOrTerminateWithError($roomplan_data);
$this->stundenplanlib->expand_object_information($roomplan_data);
$this->terminateWithSuccess($roomplan_data);
}
// gets the reservierungen of a room if the ort_kurzbz parameter is supplied otherwise gets the reservierungen of the lvplan of a student
public function Reservierungen($ort_kurzbz = null)
/**
* gets the reservierungen of a room if the ort_kurzbz parameter is
* supplied otherwise gets the reservierungen of the lvplan of a student
* @access public
*
* @param string $ort_kurzbz
* @return void
*/
public function getReservierungen($ort_kurzbz = null)
{
$this->load->library('StundenplanLib');
//form validation
$this->load->library('form_validation');
$this->form_validation->set_data($_GET);
$this->form_validation->set_rules('start_date', "StartDate", "required");
$this->form_validation->set_rules('end_date', "EndDate", "required");
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
$this->load->model('ressource/Mitarbeiter_model','MitarbeiterModel');
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
// storing the get parameter in local variables
$start_date = $this->input->get('start_date', TRUE);
$end_date = $this->input->get('end_date', TRUE);
// storing the post parameter in local variables
$start_date = $this->input->post('start_date', true);
$end_date = $this->input->post('end_date', true);
// get data
$this->load->library('StundenplanLib');
$result = $this->stundenplanlib->getReservierungen($start_date, $end_date, $ort_kurzbz);
$result = $this->stundenplanlib->getReservierungen($start_date,$end_date,$ort_kurzbz);
$result = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($result);
}
+51 -12
View File
@@ -130,30 +130,69 @@ class StundenplanLib{
}
public function getReservierungen($start_date, $end_date, $ort_kurzbz){
/**
* Get stundenplan for a room
*
* @param string $ort_kurzbz
* @param string $start_date
* @param string $end_date
* @return stdClass
*/
public function getRoomplan($ort_kurzbz, $start_date, $end_date)
{
$this->_ci =& get_instance();
// Load Config
$this->_ci->load->config('calendar');
// Load Models
$this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel');
$query = $this->_ci->StundenplanModel->getRoomQuery($ort_kurzbz, $start_date, $end_date);
$roomplan_data = $this->_ci->StundenplanModel->stundenplanGruppierung($query);
if (isError($roomplan_data))
return $roomplan_data;
$this->expand_object_information($roomplan_data->retval);
return $roomplan_data;
}
/**
* Get reservations (for a room or all)
*
* @param string $start_date
* @param string $end_date
* @param string $ort_kurzbz
* @return stdClass
*/
public function getReservierungen($start_date, $end_date, $ort_kurzbz = '')
{
$this->_ci =& get_instance();
// Load Config
$this->_ci->load->config('calendar');
// Load Models
$this->_ci->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
$is_mitarbeiter = getData($this->_ci->MitarbeiterModel->isMitarbeiter(getAuthUID()));
if($is_mitarbeiter)
{
if ($is_mitarbeiter) {
$reservierungen = $this->_ci->ReservierungModel->getReservierungenMitarbeiter($start_date, $end_date, $ort_kurzbz);
} else {
// querying the reservierungen
$reservierungen = $this->_ci->ReservierungModel->getReservierungen($start_date, $end_date, $ort_kurzbz);
}
if(isError($reservierungen))
{
return error(getData($reservierungen));
}
$reservierungen = getData($reservierungen) ?? [];
$function_error = $this->expand_object_information($reservierungen);
if(!is_null($function_error)){
if (isError($reservierungen))
return $reservierungen;
$function_error = $this->expand_object_information($reservierungen->retval);
if (!is_null($function_error))
return $function_error;
}
return success($reservierungen);
return $reservierungen;
}
public function getLektorenFromLehrveranstaltung($lehrveranstaltung_id, $semester, $studiengang_kz, $studiensemester_kurzbz){
+5 -5
View File
@@ -18,7 +18,7 @@
export default {
getRoomInfo(ort_kurzbz, start_date, end_date) {
return {
method: 'get',
method: 'post',
url: '/api/frontend/v1/LvPlan/getRoomplan',
params: { ort_kurzbz, start_date, end_date }
};
@@ -39,15 +39,15 @@ export default {
},
getOrtReservierungen(ort_kurzbz, start_date, end_date) {
return {
method: 'get',
url: `/api/frontend/v1/LvPlan/Reservierungen/${ort_kurzbz}`,
method: 'post',
url: `/api/frontend/v1/LvPlan/getReservierungen/${ort_kurzbz}`,
params: { start_date, end_date }
};
},
getLvPlanReservierungen(start_date, end_date) {
return {
method: 'get',
url: '/api/frontend/v1/LvPlan/Reservierungen',
method: 'post',
url: '/api/frontend/v1/LvPlan/getReservierungen',
params: { start_date, end_date }
};
},
+5 -5
View File
@@ -1,7 +1,7 @@
export default {
getRoomInfo(ort_kurzbz, start_date, end_date) {
return this.$fhcApi.get(
return this.$fhcApi.post(
'/api/frontend/v1/LvPlan/getRoomplan',
{ ort_kurzbz, start_date, end_date}
);
@@ -13,14 +13,14 @@ export default {
);
},
getOrtReservierungen(ort_kurzbz, start_date, end_date) {
return this.$fhcApi.get(
`/api/frontend/v1/LvPlan/Reservierungen/${ort_kurzbz}`,
return this.$fhcApi.post(
`/api/frontend/v1/LvPlan/getReservierungen/${ort_kurzbz}`,
{ start_date, end_date}
);
},
getLvPlanReservierungen(start_date, end_date) {
return this.$fhcApi.get(
'/api/frontend/v1/LvPlan/Reservierungen',
return this.$fhcApi.post(
'/api/frontend/v1/LvPlan/getReservierungen',
{ start_date, end_date }
);
},
+131 -196
View File
@@ -1,259 +1,194 @@
import FhcCalendar from "../../Calendar/Calendar.js";
import FhcCalendar from "../../Calendar/Base.js";
import CalendarDate from "../../../composables/CalendarDate.js";
import LvModal from "../../../components/Cis/Mylv/LvModal.js";
import LvInfo from "../../../components/Cis/Mylv/LvInfo.js"
import ApiStudenplan from '../../../api/factory/lvPlan.js';
import { useEventLoader } from '../../../composables/EventLoader.js';
import ModeDay from '../../Calendar/Mode/Day.js';
import ModeWeek from '../../Calendar/Mode/Week.js';
import ModeMonth from '../../Calendar/Mode/Month.js';
export const DEFAULT_MODE_RAUMINFO = 'Week'
const RoomInformation = {
export default {
name: "RoomInformation",
props:{
propsViewData: {
type: Object
},
rowMinHeight: {
type: String,
default: '100px'
},
eventMaxHeight: {
type: String,
default: '125px'
}
},
components: {
FhcCalendar,
LvModal,
LvInfo,
LvInfo
},
provide() {
return {
rowMinHeight: this.rowMinHeight,
eventMaxHeight: this.eventMaxHeight
}
inject: [
"renderers"
],
props:{
viewData: Object, // NOTE(chris): this is inherited from router-view
propsViewData: Object
},
data() {
const now = luxon.DateTime.now().setZone(this.viewData.timezone);
return {
events: null,
calendarMode: DEFAULT_MODE_RAUMINFO,
calendarDate: new CalendarDate(new Date()),
currentlySelectedEvent: null,
currentDay: this.propsViewData?.focus_date ? new Date(this.propsViewData.focus_date) : new Date(),
minimized: false,
modes: {
day: Vue.markRaw(ModeDay),
week: Vue.markRaw(ModeWeek),
month: Vue.markRaw(ModeMonth)
},
modeOptions: {
day: {
emptyMessage: Vue.computed(() => this.$p.t('rauminfo/keineRaumReservierung')),
emptyMessageDetails: Vue.computed(() => this.$p.t('rauminfo/keineRaumReservierung')),
compact: false
},
week: {
collapseEmptyDays: false
}
},
computed:{
currentDate: function(){
return new Date(this.calendarWeek.y, this.calendarWeek.m, this.calendarWeek.d);
},
weekFirstDay: function () {
return this.calendarDateToString(this.calendarDate.cdFirstDayOfWeek);
},
weekLastDay: function () {
return this.calendarDateToString(this.calendarDate.cdLastDayOfWeek);
},
monthFirstDay: function () {
return this.calendarDateToString(this.calendarDate.cdFirstDayOfCalendarMonth);
},
monthLastDay: function () {
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)
currentDay: this.propsViewData?.focus_date,
calendarMode: this.propsViewData?.mode ?? DEFAULT_MODE_RAUMINFO,
backgrounds: [
{
class: 'background-past',
end: now,
label: now.startOf('minute').toISOTime({ suppressSeconds: true, includeOffset: false })
}
]
}
},
methods:{
setSelectedEvent: function(event){
this.currentlySelectedEvent = event;
eventStyle(event) {
if (!event.farbe)
return undefined;
return '--event-bg:#' + event.farbe;
},
getLvID: function () {
this.lv_id = window.location.pathname
},
selectDay: function(day){
const date = day.getFullYear() + "-" +
String(day.getMonth() + 1).padStart(2, "0") + "-" +
String(day.getDate()).padStart(2, "0");
handleChangeDate(day) {
const focus_date = day.toISODate();
const mode = this.calendarMode[0].toUpperCase() + this.calendarMode.slice(1);
this.$router.push({
name: "RoomInformation",
params: {
mode: this.calendarMode,
focus_date: date,
mode,
focus_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: "LvPlan",
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");
handleChangeMode(newMode) {
const mode = newMode[0].toUpperCase() + newMode.slice(1)
const focus_date = (this.currentDay instanceof luxon.DateTime)
? this.currentDay.toISODate()
: this.currentDay;
this.$router.push({
name: "RoomInformation",
params: {
mode: modeCapitalized,
focus_date: date,
mode,
focus_date,
ort_kurzbz: this.propsViewData.ort_kurzbz
}
})
this.calendarMode = mode
},
showModal: function (event) {
this.currentlySelectedEvent = event;
Vue.nextTick(() => {
this.$refs.lvmodal.show();
updateRange(rangeInterval) {
this.rangeInterval = rangeInterval;
}
},
setup(props) {
const $api = Vue.inject('$api');
const rangeInterval = Vue.ref(null);
const { events } = useEventLoader(rangeInterval, (start, end) => {
return [
$api.call(ApiStudenplan.getRoomInfo(props.propsViewData.ort_kurzbz, start.toISODate(), end.toISODate())),
$api.call(ApiStudenplan.getOrtReservierungen(props.propsViewData.ort_kurzbz, start.toISODate(), end.toISODate()))
];
});
},
updateRange: function ({ start, end }) {
let checkDate = (date) => {
return date.m != this.calendarDate.m || date.y != this.calendarDate.y;
}
// only load month data if the month or year has changed
if (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.calendarDate = new CalendarDate(end);
Vue.nextTick(() => {
this.loadEvents();
});
}
},
calendarDateToString: function (calendarDate) {
return calendarDate instanceof CalendarDate ?
[calendarDate.y, calendarDate.m + 1, calendarDate.d].join('-') :
null;
},
loadEvents: function(){
// bundles the room_events and the reservierungen together into the this.events array
Promise.allSettled([
this.$api.call(ApiStudenplan.getRoomInfo(this.propsViewData.ort_kurzbz, this.monthFirstDay, this.monthLastDay)),
this.$api.call(ApiStudenplan.getOrtReservierungen(this.propsViewData.ort_kurzbz, 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;
})
},
},
created() {
this.loadEvents();
return {
rangeInterval,
events
};
},
template: /*html*/`
<div class="fhc-roominformation d-flex flex-column h-100">
<h2>{{ $p.t('rauminfo/rauminfo') }} {{ propsViewData.ort_kurzbz }}</h2>
<hr>
<lv-modal v-if="currentlySelectedEvent" :showMenu="false" :event="currentlySelectedEvent" ref="lvmodal" />
<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"
:date="currentDay"
:modes="modes"
:mode-options="modeOptions"
:mode="propsViewData.mode.toLowerCase()"
@update:date="handleChangeDate"
@update:mode="handleChangeMode"
@update:range="updateRange"
:timezone="viewData.timezone"
:locale="$p.user_locale.value"
show-btns
:events="events || []"
:backgrounds="backgrounds"
>
<template #monthPage="{event,day}">
<span >
{{event.topic}}
</span>
</template>
<template #weekPage="{event,day}">
<div @click="showModal(event)" type="button" class=" border border-secondary border d-flex flex-column align-items-center justify-content-evenly h-100">
<span>{{event?.topic}}</span>
<span v-for="lektor in event?.lektor">{{lektor.kurzbz}}</span>
<span>{{event?.ort_kurzbz}}</span>
<template v-slot="{ event, mode }">
<component
v-if="mode == 'event'"
:is="renderers[event.type]?.modalContent"
:event="event"
></component>
<component
v-else-if="mode == 'eventheader'"
:is="renderers[event.type]?.modalTitle"
:event="event"
></component>
<div
v-else-if="mode == 'month'"
:class="'event-type-' + event.type"
:style="eventStyle(event)"
class="d-flex flex-column align-items-center justify-content-evenly h-100"
>
<span>{{ event?.topic }}</span>
</div>
</template>
<template #dayPage="{event,day,mobile}">
<div @click="mobile? showModal(event):null" type="button" class="fhc-entry border border-secondary border row h-100 justify-content-center align-items-center text-center">
<div
v-else-if="mode == 'week'"
:class="'event-type-' + event.type"
:style="eventStyle(event)"
class="border border-secondary d-flex flex-column align-items-center justify-content-evenly h-100"
type="button"
>
<span>{{ event?.topic }}</span>
<span v-for="lektor in event?.lektor">{{ lektor.kurzbz }}</span>
<span>{{ event?.ort_kurzbz }}</span>
</div>
<div
v-else-if="mode == 'day'"
:class="'event-type-' + event.type"
:style="eventStyle(event)"
type="button"
class="border border-secondary d-flex align-items-center justify-content-center text-center h-100"
>
<div class="col ">
<p>{{ $p.t('lehre/lehrveranstaltung') }}:</p>
<p class="m-0">{{event?.topic}}</p>
<p class="m-0">
{{ event?.topic }}
</p>
</div>
<div class="col ">
<p>{{ $p.t('lehre/lektor') }}:</p>
<p class="m-0" v-for="lektor in event?.lektor">{{lektor.kurzbz}}</p>
<p class="m-0" v-for="lektor in event?.lektor">
{{ lektor.kurzbz }}
</p>
</div>
<div class="col ">
<p>{{ $p.t('profil/Ort') }}: </p>
<p class="m-0">{{event?.ort_kurzbz}}</p>
<p class="m-0">
{{ event?.ort_kurzbz }}
</p>
</div>
</div>
</template>
<template #pageMobilContent>
<h3 >{{$p.t('lvinfo','lehrveranstaltungsinformationen')}}</h3>
<div class="w-100">
<lv-info :event="currentlySelectedEvent" />
</div>
</template>
<template #pageMobilContentEmpty >
<h3>{{$p.t('rauminfo','keineRaumReservierung')}}</h3>
</template>
</fhc-calendar>
`,
</div>`
};
export default RoomInformation