mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-21 22:19:27 +00:00
legacy raumsuche.php -> cis4 vue component
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Raumsuche extends Auth_Controller
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'index' => ['basis/cis:r']
|
||||
]);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
||||
$viewData = array(
|
||||
'uid'=>getAuthUID(),
|
||||
);
|
||||
|
||||
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Raumsuche']);
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,8 @@ class Ort extends FHCAPI_Controller
|
||||
parent::__construct([
|
||||
'ContentID' => self::PERM_LOGGED,
|
||||
'getOrtKurzbzContent' => self::PERM_LOGGED,
|
||||
'getRooms' => self::PERM_LOGGED,
|
||||
'getTypes' => self::PERM_LOGGED
|
||||
]);
|
||||
|
||||
$this->load->model('ressource/Ort_model', 'OrtModel');
|
||||
@@ -44,6 +46,57 @@ class Ort extends FHCAPI_Controller
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* Retrieves all Ort entries filtered by the provided parameters
|
||||
*/
|
||||
public function getRooms()
|
||||
{
|
||||
// TODO: form validation
|
||||
$datum = $this->input->get('datum', TRUE);
|
||||
$von = $this->input->get('von', TRUE);
|
||||
$bis = $this->input->get('bis', TRUE);
|
||||
$typ = $this->input->get('typ', TRUE);
|
||||
$personenanzahl = $this->input->get('personenanzahl', TRUE);
|
||||
|
||||
$this->load->model('ressource/Stunde_model', 'StundeModel');
|
||||
$vonStunde = getData($this->StundeModel->getStundeForTime($von))[0]->stunde;
|
||||
$bisStunde = getData($this->StundeModel->getStundeForTime($bis))[0]->stunde;
|
||||
|
||||
$params = array();
|
||||
$qry = "SELECT DISTINCT tbl_ort.*
|
||||
FROM public.tbl_ort JOIN public.tbl_ortraumtyp USING(ort_kurzbz)
|
||||
WHERE aktiv AND lehre AND ort_kurzbz NOT LIKE '\\\\_%'";
|
||||
if($typ) {
|
||||
$params[] = $typ;
|
||||
$qry.= "AND raumtyp_kurzbz= ?";
|
||||
}
|
||||
$qry.= "AND (max_person>= ? OR max_person is null)";
|
||||
$params[] = $personenanzahl;
|
||||
|
||||
$qry.=" AND ort_kurzbz NOT IN
|
||||
(
|
||||
SELECT ort_kurzbz FROM lehre.tbl_stundenplandev WHERE datum=? AND stunde>=? AND stunde<=?
|
||||
UNION
|
||||
SELECT ort_kurzbz FROM campus.tbl_reservierung WHERE datum=? AND stunde>=? AND stunde<=?
|
||||
)
|
||||
";
|
||||
$params = array_merge($params, [$datum, $vonStunde, $bisStunde, $datum, $vonStunde, $bisStunde]);
|
||||
|
||||
$result = $this->OrtModel->execReadOnlyQuery($qry, $params);
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
|
||||
public function getTypes()
|
||||
{
|
||||
$this->load->model('ressource/Raumtyp_model', 'RaumtypModel');
|
||||
$result = $this->OrtModel->execReadOnlyQuery("
|
||||
SELECT * FROM public.tbl_raumtyp WHERE aktiv = true ORDER BY raumtyp_kurzbz;
|
||||
");
|
||||
|
||||
$this->terminateWithSuccess(getData($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a JSON body via HTTP POST and provides the parameters
|
||||
*/
|
||||
|
||||
@@ -11,4 +11,19 @@ class Stunde_model extends DB_Model
|
||||
$this->dbTable = 'lehre.tbl_stunde';
|
||||
$this->pk = 'stunde';
|
||||
}
|
||||
|
||||
/**
|
||||
* $time needs to be of PGSQL TIME format
|
||||
*/
|
||||
public function getStundeForTime($time) {
|
||||
$query = "
|
||||
SELECT min(stunde) as stunde FROM (
|
||||
SELECT stunde, extract(epoch from (beginn-?)) AS delta FROM lehre.tbl_stunde
|
||||
UNION
|
||||
SELECT stunde, extract(epoch from (ende-?)) AS delta FROM lehre.tbl_stunde
|
||||
) foo WHERE delta>=0
|
||||
";
|
||||
|
||||
return $this->execReadOnlyQuery($query, [$time, $time]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ $includesArray = array(
|
||||
'axios027' => true,
|
||||
'bootstrap5' => true,
|
||||
'fontawesome6' => true,
|
||||
'tabulator5' => true,
|
||||
'tabulator5' => true, // TODO: upgrade to 6 when available
|
||||
'vue3' => true,
|
||||
'primevue3' => true,
|
||||
'vuedatepicker11' => true,
|
||||
@@ -24,7 +24,8 @@ $includesArray = array(
|
||||
),
|
||||
'customJSs' => array(
|
||||
'vendor/npm-asset/primevue/accordion/accordion.js',
|
||||
'vendor/npm-asset/primevue/accordiontab/accordiontab.js'
|
||||
'vendor/npm-asset/primevue/accordiontab/accordiontab.js',
|
||||
'vendor/npm-asset/primevue/inputnumber/inputnumber.js'
|
||||
),
|
||||
'customJSModules' => array(
|
||||
'public/js/apps/Dashboard/Fhc.js'
|
||||
|
||||
@@ -60,5 +60,5 @@ export default {
|
||||
addons,
|
||||
studiengang,
|
||||
menu,
|
||||
authinfo,
|
||||
authinfo
|
||||
};
|
||||
|
||||
@@ -7,4 +7,19 @@ export default {
|
||||
{ ort_kurzbz: ort_kurbz }
|
||||
);
|
||||
},
|
||||
getRooms(datum, von, bis, typ, personenanzahl = 0) {
|
||||
return this.$fhcApi.get(
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router +
|
||||
"/api/frontend/v1/Ort/getRooms",
|
||||
{ datum, von, bis, typ, personenanzahl }
|
||||
);
|
||||
},
|
||||
getRoomTypes() {
|
||||
return this.$fhcApi.get(
|
||||
FHC_JS_DATA_STORAGE_OBJECT.app_root +
|
||||
FHC_JS_DATA_STORAGE_OBJECT.ci_router +
|
||||
"/api/frontend/v1/Ort/getTypes"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import {setScrollbarWidth} from "../../helpers/CssVarCalcHelpers.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 Raumsuche from "../../components/Cis/Raumsuche/Raumsuche.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";
|
||||
@@ -28,7 +29,12 @@ const router = VueRouter.createRouter({
|
||||
component: Profil,
|
||||
props: true
|
||||
},
|
||||
|
||||
{
|
||||
path: `/Cis/Raumsuche`,
|
||||
name: 'Raumsuche',
|
||||
component: Raumsuche,
|
||||
props: true
|
||||
},
|
||||
// Redirect old links to new format
|
||||
{
|
||||
path: "/CisVue/Cms/getRoomInformation/:ort_kurzbz",
|
||||
|
||||
@@ -76,6 +76,7 @@ export default {
|
||||
this.$refs.studiensemester.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
},
|
||||
setHash(val) {
|
||||
// TODO: make this a router param to enable history
|
||||
location.hash = val;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
|
||||
import {CoreFilterCmpt} from "../../../components/filter/Filter.js";
|
||||
|
||||
export default {
|
||||
name: "Raumsuche",
|
||||
props: {
|
||||
|
||||
},
|
||||
components: {
|
||||
VueDatePicker,
|
||||
CoreFilterCmpt,
|
||||
InputNumber: primevue.inputnumber,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tabulatorUuid: Vue.ref(0),
|
||||
tableBuiltResolve: null,
|
||||
tableBuiltPromise: null,
|
||||
roomtypes: null,
|
||||
defaultType: {
|
||||
raumtyp_kurzbz: '',
|
||||
beschreibung: Vue.computed(() => this.$p.t('global/alle'))
|
||||
},
|
||||
anzahl: 1,
|
||||
selectedType: null,
|
||||
datum: new Date(),
|
||||
von: Vue.ref({
|
||||
hours: new Date().getHours(),
|
||||
minutes: new Date().getMinutes()
|
||||
}),
|
||||
bis: Vue.ref({
|
||||
hours: new Date().getHours() + 1,
|
||||
minutes: new Date().getMinutes()
|
||||
}),
|
||||
raumsucheTableOptions: {
|
||||
height: Vue.ref(400),
|
||||
index: 'prestudent_id',
|
||||
layout: 'fitColumns',
|
||||
placeholder: this.$p.t('global/noDataAvailable'),
|
||||
columns: [
|
||||
{title: Vue.computed(() => this.$p.t('rauminfo/raum_kurzbz')), field: 'ort_kurzbz', widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$p.t('global/bezeichnung')), field: 'bezeichnung', widthGrow: 2},
|
||||
{title: Vue.computed(() => this.$p.t('global/nummer')), field: 'nummer', widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$p.t('global/personen')), field: 'personen', widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$p.t('rauminfo/raumInfo')),
|
||||
field: 'linkInfo', formatter: this.linkFormatter, widthGrow: 1},
|
||||
{title: Vue.computed(() => this.$p.t('rauminfo/roomReservations')),
|
||||
field: 'linkRes', formatter: this.linkFormatter, widthGrow: 1}
|
||||
],
|
||||
persistence: false,
|
||||
},
|
||||
raumsucheTableEventHandlers: [{
|
||||
event: "tableBuilt",
|
||||
handler: async () => {
|
||||
this.tableBuiltResolve()
|
||||
}
|
||||
},
|
||||
{
|
||||
event: "cellClick",
|
||||
handler: async (e, cell) => {
|
||||
|
||||
if((cell.column.field === 'linkInfo' || cell.column.field === 'linkRes') && cell.value){
|
||||
window.open(cell.value, '_blank');
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
]};
|
||||
},
|
||||
methods: {
|
||||
tableResolve(resolve) {
|
||||
this.tableBuiltResolve = resolve
|
||||
},
|
||||
linkFormatter(cell) {
|
||||
const val = cell.getValue()
|
||||
if(val) {
|
||||
return '<div style="display: flex; justify-content: center; align-items: center; height: 100%">' +
|
||||
'<a href="'+val+'"><i class="fa fa-arrow-up-right-from-square me-1" style="color:#00649C"></i></a></div>'
|
||||
} else {
|
||||
return '<div style="display: flex; justify-content: center; align-items: center; height: 100%">' +
|
||||
'-</div>'
|
||||
}
|
||||
},
|
||||
roomPlanLink(room) {
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router
|
||||
+ '/CisVue/Cms/getRoomInformation/' + room.ort_kurzbz
|
||||
},
|
||||
roomInfoLink(room) {
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router
|
||||
+ '/CisVue/Cms/content/' + room.content_id
|
||||
},
|
||||
getTimeString(time) {
|
||||
return `${time.hours}:${time.minutes}:00`
|
||||
},
|
||||
setupData(data){
|
||||
const d = data.map(room => {
|
||||
return {
|
||||
ort_kurzbz: room.ort_kurzbz,
|
||||
bezeichnung: room.bezeichnung,
|
||||
nummer: room.planbezeichnung,
|
||||
personen: room.max_person,
|
||||
linkInfo: room.content_id ? this.roomInfoLink(room) : null,
|
||||
linkRes: this.roomPlanLink(room)
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
this.$refs.raumsucheTable.tabulator.setData(d);
|
||||
},
|
||||
loadRoomTypes() {
|
||||
this.$fhcApi.factory.ort.getRoomTypes().then(res => {
|
||||
this.selectedType = this.defaultType
|
||||
this.roomtypes = res?.data ?? []
|
||||
})
|
||||
},
|
||||
loadRooms() {
|
||||
this.$fhcApi.factory.ort.getRooms(this.date, this.getTimeString(this.von), this.getTimeString(this.bis), this.selectedType?.raumtyp_kurzbz ?? '', this.anzahl)
|
||||
.then(res => {
|
||||
if(res?.data?.retval) this.setupData(res.data.retval)
|
||||
})
|
||||
},
|
||||
handleUuidDefined(uuid) {
|
||||
this.tabulatorUuid = uuid
|
||||
},
|
||||
search(){
|
||||
this.loadRooms()
|
||||
},
|
||||
setRoute(val) {
|
||||
// TODO: router push
|
||||
},
|
||||
dateFormat(date) {
|
||||
const day = date.getDate();
|
||||
const month = date.getMonth() + 1;
|
||||
const year = date.getFullYear();
|
||||
return `${day}.${month}.${year}`
|
||||
},
|
||||
timeFormat(date) {
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
return `${hours}:${minutes}`;
|
||||
},
|
||||
async setupMounted() {
|
||||
this.tableBuiltPromise = new Promise(this.tableResolve)
|
||||
await this.tableBuiltPromise
|
||||
|
||||
this.loadRoomTypes()
|
||||
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')
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.setupMounted()
|
||||
},
|
||||
template: `
|
||||
<h2>{{$p.t('lvplan/raumsuche')}}</h2>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<VueDatePicker
|
||||
v-model="datum"
|
||||
:clearable="false"
|
||||
date-picker
|
||||
:enable-time="false"
|
||||
:format="dateFormat"
|
||||
text-input="true"
|
||||
auto-apply>
|
||||
</VueDatePicker>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<VueDatePicker
|
||||
v-model="von"
|
||||
:clearable="false"
|
||||
time-picker
|
||||
:format="timeFormat"
|
||||
text-input="true"
|
||||
auto-apply
|
||||
>
|
||||
</VueDatePicker>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
<VueDatePicker
|
||||
v-model="bis"
|
||||
:clearable="false"
|
||||
time-picker
|
||||
:format="timeFormat"
|
||||
text-input="true"
|
||||
auto-apply>
|
||||
</VueDatePicker>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<select ref="raumtyp" id="raumtypSelect" v-model="selectedType" class="form-select"
|
||||
:aria-label="$p.t('global/studiensemester_auswaehlen')" @change="setRoute($event.target.value)">
|
||||
<option :key="defaultType" selected :value="defaultType">{{defaultType.beschreibung}}</option>
|
||||
<option v-for="typ in roomtypes" :key="typ" :value="typ">{{typ.beschreibung}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<InputNumber v-model="anzahl" :prefix="$p.t('rauminfo/anzahlPersonen') + ': '" inputId="anzahlInput" :min="1" :max="100" />
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<button class="btn btn-primary border-0" @click="search">{{ $p.t('rauminfo/roomSearch') }} <i class="fa fa-magnifying-glass"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<core-filter-cmpt
|
||||
@tableBuilt="raumsucheTableBuilt"
|
||||
@uuidDefined="handleUuidDefined"
|
||||
:title="''"
|
||||
ref="raumsucheTable"
|
||||
:tabulator-options="raumsucheTableOptions"
|
||||
:tabulator-events="raumsucheTableEventHandlers"
|
||||
tableOnly
|
||||
:sideMenu="false"
|
||||
/>
|
||||
`,
|
||||
};
|
||||
@@ -20184,6 +20184,26 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'rauminfo',
|
||||
'phrase' => 'raum_kurzbz',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Raum Kurzbezeichnung",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "Room Shortname",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'rauminfo',
|
||||
@@ -20204,6 +20224,66 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'rauminfo',
|
||||
'phrase' => 'roomSearch',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Räume Suchen",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "Search Rooms",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'rauminfo',
|
||||
'phrase' => 'anzahlPersonen',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Anzahl Person",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "Number of People",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'rauminfo',
|
||||
'phrase' => 'roomReservations',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => "Raum Reservierungen",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => "Room Reservations",
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'rauminfo',
|
||||
|
||||
Reference in New Issue
Block a user