mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-10-12 06:54:04 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
67bbe9c105 |
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2024 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
class Reservierung extends FHCAPI_Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Object initialization
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'getMyReservation' => 'basis/cis:r',
|
||||
'deleteReservation' => 'lehre/reservierung:rw'
|
||||
]);
|
||||
|
||||
$this->load->model('ressource/Reservierung_model', 'ReservierungModel');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all reservations from lehre.vw_reservation of the logged in user
|
||||
*/
|
||||
public function getMyReservation()
|
||||
{
|
||||
$result = $this->ReservierungModel->getMyReservation();
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* deletes a reservation by ID
|
||||
*/
|
||||
public function deleteReservation()
|
||||
{
|
||||
$reservierung_id = $this->input->post('reservierung_id');
|
||||
|
||||
|
||||
if ($reservierung_id === NULL || trim((string)$reservierung_id) === '') {
|
||||
$this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general');
|
||||
}
|
||||
|
||||
$result = $this->ReservierungModel->deleteReservation($reservierung_id);
|
||||
$data = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
$this->terminateWithSuccess($data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,4 +146,40 @@ class Reservierung_model extends DB_Model
|
||||
return $this->execReadOnlyQuery($qry, [$uid, $datum, $stunde]);
|
||||
}
|
||||
|
||||
public function deleteReservation($reservierung_id) {
|
||||
$uid = getAuthUID();
|
||||
|
||||
$result = $this->load($reservierung_id);
|
||||
|
||||
if (isError($result))
|
||||
return $result;
|
||||
|
||||
if (!hasData($result))
|
||||
return error('Reservierung nicht gefunden');
|
||||
|
||||
$row = $result->retval[0];
|
||||
|
||||
if ($row->uid !== $uid && $row->insertvon !== $uid)
|
||||
return error('Keine Berechtigung');
|
||||
|
||||
return $this->delete($reservierung_id);
|
||||
}
|
||||
|
||||
public function getMyReservation() {
|
||||
$uid = getAuthUID();
|
||||
$date = date("Y-m-d",time());
|
||||
|
||||
$qry = "SELECT vw_reservierung.*,
|
||||
trim(COALESCE(vw_mitarbeiter.titelpre,'')||' '||COALESCE(vw_mitarbeiter.vorname,'')||' '||COALESCE(vw_mitarbeiter.nachname,'')||' '||COALESCE(vw_mitarbeiter.titelpost,'')) as reserviert_fuer,
|
||||
trim(COALESCE(reserviert_von.titelpre,'')||' '||COALESCE(reserviert_von.vorname,'')||' '||COALESCE(reserviert_von.nachname,'')||' '||COALESCE(reserviert_von.titelpost,'')) as reserviert_von
|
||||
FROM campus.vw_reservierung
|
||||
JOIN campus.vw_mitarbeiter ON vw_reservierung.uid=vw_mitarbeiter.uid
|
||||
LEFT JOIN campus.vw_mitarbeiter reserviert_von ON vw_reservierung.insertvon=reserviert_von.uid
|
||||
WHERE datum >= ?
|
||||
AND (vw_reservierung.uid= ? OR vw_reservierung.insertvon= ? )
|
||||
ORDER BY datum, titel, ort_kurzbz, stunde";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, [$date, $uid, $uid]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright (C) 2025 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
getMyReservation() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Reservierung/getMyReservation',
|
||||
};
|
||||
},
|
||||
deleteReservation(reservierung_id) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Reservierung/deleteReservation',
|
||||
params: { reservierung_id }
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -8,6 +8,7 @@ import MyLvPlan from "../../components/Cis/LvPlan/MyLvPlan.js";
|
||||
import MylvStudent from "../../components/Cis/Mylv/Student.js";
|
||||
import Profil from "../../components/Cis/Profil/Profil.js";
|
||||
import Raumsuche from "../../components/Cis/Raumsuche/Raumsuche.js";
|
||||
import MyReservation from "../../components/Cis/MyReservation/MyReservation.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";
|
||||
@@ -77,6 +78,12 @@ const router = VueRouter.createRouter({
|
||||
component: Raumsuche,
|
||||
props: true
|
||||
},
|
||||
{
|
||||
path: `/Cis/MyReservation`,
|
||||
name: 'MyReservation',
|
||||
component: MyReservation,
|
||||
props: true
|
||||
},
|
||||
// Redirect old links to new format
|
||||
{
|
||||
path: "/CisVue/Cms/getRoomInformation/:ort_kurzbz",
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
import {CoreFilterCmpt} from "../../../components/filter/Filter.js";
|
||||
import VueDatePicker from '../../vueDatepicker.js.php';
|
||||
import ApiReservierung from '../../../api/factory/reservierung.js'
|
||||
import { formatISODate } from "../Abgabetool/dateUtils.js";
|
||||
|
||||
export const MyReservation = {
|
||||
name: "MyReservation",
|
||||
components: {
|
||||
VueDatePicker,
|
||||
CoreFilterCmpt
|
||||
},
|
||||
inject: ["isMobile"],
|
||||
data() {
|
||||
return {
|
||||
phrasenPromise: null,
|
||||
phrasenResolved: false,
|
||||
tabulatorUuid: Vue.ref(0),
|
||||
tableBuiltResolve: null,
|
||||
tableBuiltPromise: null,
|
||||
myReservationTableOptions: {
|
||||
minHeight: 250,
|
||||
index: 'reservierung_id',
|
||||
layout: 'fitColumns',
|
||||
placeholder: this.$p.t('global/noDataAvailable'),
|
||||
columns: [
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('global/datum'))), field: 'datum', widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('global/titel'))), field: 'titel', widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('ui/stunde'))), field: 'stunde', widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('global/raum'))), field: 'ort_kurzbz', widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('reservierung/reserviert_fuer'))), field: 'reserviert_fuer', widthGrow: 2},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('global/beschreibung'))), field: 'beschreibung', widthGrow: 2},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('reservierung/reserviert_von'))), field: 'reserviert_von', widthGrow: 2},
|
||||
{title: Vue.computed(() => this.$capitalize(this.$p.t('global/actions'))), field: 'aktion', formatter: this.formAction, widthGrow: 1}
|
||||
],
|
||||
persistence: false,
|
||||
},
|
||||
myReservationTableEventHandlers: [{
|
||||
event: "tableBuilt",
|
||||
handler: async () => {
|
||||
this.tableBuiltResolve()
|
||||
}
|
||||
}
|
||||
]};
|
||||
},
|
||||
computed: {
|
||||
isDarkMode(){
|
||||
return this.$theme.theme_name.value == 'dark';
|
||||
},
|
||||
generalPresets: function() {
|
||||
return [
|
||||
{
|
||||
"id": null,
|
||||
"name": "Standard",
|
||||
"displayedColumns": [
|
||||
"datum","titel","stunde","ort_kurzbz","reserviert_fuer",
|
||||
"reserviert_fuer", "reserviert_von", "aktion"
|
||||
],
|
||||
"headerFilters": [],
|
||||
"sort": null
|
||||
}
|
||||
];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
formAction(cell) {
|
||||
const actionButtons = document.createElement('div');
|
||||
actionButtons.className = "d-flex gap-3";
|
||||
actionButtons.style.display = "flex";
|
||||
actionButtons.style.alignItems = "stretch";
|
||||
actionButtons.style.justifyContent = "start";
|
||||
actionButtons.style.height = "100%";
|
||||
|
||||
const data = cell.getRow().getData();
|
||||
|
||||
const createButton = (iconClass, titleKey, clickHandler) => {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'btn btn-outline-secondary';
|
||||
btn.style.display = "flex";
|
||||
btn.style.alignItems = "center"; // center icon vertically
|
||||
btn.style.justifyContent = "center"; // center icon horizontally
|
||||
btn.style.height = "100%"; // fill parent container height
|
||||
btn.style.aspectRatio = "1 / 1"; // keep square shape (optional)
|
||||
btn.style.padding = "0"; // remove extra padding for compactness
|
||||
if(iconClass == 'fa fa-timeline') btn.style.transform = "rotate(90deg)";
|
||||
btn.innerHTML = `<i class="${iconClass}" style="color:#00649C; font-size:1.1rem;"></i>`;
|
||||
btn.title = this.$capitalize(this.$p.t(titleKey));
|
||||
btn.addEventListener('click', (e) => {
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
clickHandler();
|
||||
});
|
||||
return btn;
|
||||
};
|
||||
|
||||
// TODO: only show/enable this button if user has berechtigung 'lehre/reservierung:begrenzt'
|
||||
|
||||
actionButtons.append(
|
||||
createButton('fa fa-trash-can', 'global/delete', () => this.deleteReservation(data)),
|
||||
);
|
||||
|
||||
return actionButtons;
|
||||
},
|
||||
deleteReservation(data) {
|
||||
this.$api.call(ApiReservierung.deleteReservation(data.reservierung_id))
|
||||
.then(res => {
|
||||
if(res?.meta.status === 'success') {
|
||||
this.$refs.myReservationTable.tabulator.deleteRow(data.reservierung_id);
|
||||
this.$fhcAlert.alertSuccess(this.$p.t('reservierung/reservierungWurdeGeloescht'));
|
||||
}
|
||||
})
|
||||
},
|
||||
tableResolve(resolve) {
|
||||
this.tableBuiltResolve = resolve
|
||||
},
|
||||
setupData(data){
|
||||
const d = data.map(reservation => {
|
||||
return {
|
||||
...reservation, // spread first, then format date
|
||||
datum: formatISODate(reservation.datum),
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
this.$refs.myReservationTable.tabulator.setData(d);
|
||||
},
|
||||
handleUuidDefined(uuid) {
|
||||
this.tabulatorUuid = uuid
|
||||
},
|
||||
loadMyReservation() {
|
||||
this.$api.call(ApiReservierung.getMyReservation())
|
||||
.then(res => {
|
||||
if(res?.data) this.setupData(res.data)
|
||||
})
|
||||
},
|
||||
async setupMounted() {
|
||||
|
||||
this.tableBuiltPromise = new Promise(this.tableResolve)
|
||||
await this.tableBuiltPromise
|
||||
|
||||
|
||||
|
||||
this.loadMyReservation()
|
||||
// this.loadRooms()
|
||||
//
|
||||
// const tableID = this.tabulatorUuid ? ('-' + this.tabulatorUuid) : ''
|
||||
// const tableDataSet = document.getElementById('filterTableDataset' + tableID);
|
||||
// if(!tableDataSet) return
|
||||
// const rect = tableDataSet.getBoundingClientRect();
|
||||
//
|
||||
// const h = window.visualViewport.height - rect.top - 100
|
||||
// if(this.$refs.raumsucheTable) {
|
||||
// this.$refs.raumsucheTable.$refs.table.style.setProperty('height', h+'px')
|
||||
// }
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.phrasenPromise = this.$p.loadCategory(['reservierung', 'global', 'ui'])
|
||||
this.phrasenPromise.then(()=> {this.phrasenResolved = true})
|
||||
},
|
||||
mounted() {
|
||||
this.setupMounted()
|
||||
},
|
||||
template: `
|
||||
<h1 class="h3">{{$p.t('reservierung/reservierungsliste')}}</h1>
|
||||
<hr>
|
||||
|
||||
<core-filter-cmpt
|
||||
v-if="phrasenResolved"
|
||||
:isUsingPresets="true"
|
||||
presetsId="myReservationTable"
|
||||
@uuidDefined="handleUuidDefined"
|
||||
:title="''"
|
||||
ref="myReservationTable"
|
||||
:tabulator-options="myReservationTableOptions"
|
||||
:tabulator-events="myReservationTableEventHandlers"
|
||||
tableOnly
|
||||
:sideMenu="false"
|
||||
/>
|
||||
`,
|
||||
};
|
||||
|
||||
export default MyReservation;
|
||||
@@ -62351,6 +62351,87 @@ I have been informed that I am under no obligation to consent to the transmissio
|
||||
)
|
||||
)
|
||||
),
|
||||
//******************* CORE/reservierung
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'reservierung',
|
||||
'phrase' => 'reservierungsliste',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Reservierungsliste',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Reservation list',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'reservierung',
|
||||
'phrase' => 'reserviert_fuer',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Reserviert für',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Reserved for',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'reservierung',
|
||||
'phrase' => 'reserviert_von',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Reserviert von',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Reserved by',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'reservierung',
|
||||
'phrase' => 'reservierungWurdeGeloescht',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Reservierung wurde gelöscht',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Reservation successfully deleted',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user