Add dedicated room req class, add tabulator backend sortings and other stuff

This commit is contained in:
Ivymaster
2026-05-20 13:01:24 +02:00
parent eca9b22f7d
commit 363cb90019
10 changed files with 720 additions and 202 deletions
-2
View File
@@ -34,8 +34,6 @@ class RoomManager extends Auth_Controller
);
$this->_setAuthUID();
$this->setControllerId();
}
// -----------------------------------------------------------------------------------------------------------------
+60 -85
View File
@@ -44,6 +44,7 @@ class Ort extends FHCAPI_Controller
]);
$this->load->library('form_validation');
$this->load->library('requests/RoomRequest');
$this->load->model('ressource/Ort_model', 'OrtModel');
$this->load->model('ressource/Reservierung_model', 'ReservierungModel');
@@ -53,8 +54,12 @@ class Ort extends FHCAPI_Controller
$this->loadPhrases([
'global',
'ui',
'lehre'
'lehre',
'gruppenmanagement',
'person',
]);
}
//------------------------------------------------------------------------------------------------------------------
@@ -73,8 +78,8 @@ class Ort extends FHCAPI_Controller
$query = "SELECT
COUNT(*) OVER() AS full_count,
public.tbl_ort.*,
pr.ort_kurzbz as pr_ort_kurzbz,
org.bezeichnung as org_bezeichnung
org.bezeichnung as org_bezeichnung,
org.organisationseinheittyp_kurzbz as org_organisationseinheittyp_kurzbz
FROM public.tbl_ort
LEFT JOIN public.tbl_ort as pr ON pr.ort_kurzbz = public.tbl_ort.parent_ort_kurzbz
LEFT JOIN public.tbl_organisationseinheit as org ON org.oe_kurzbz = public.tbl_ort.oe_kurzbz";
@@ -87,6 +92,16 @@ class Ort extends FHCAPI_Controller
$searchableBooleanAttributes = ['lehre', 'reservieren', 'aktiv'];
$searchableNumericAttributes = ['max_person', 'arbeitsplaetze', 'kosten', 'stockwerk'];
$searchableNumericSpanAttributes = ['m2'];
$searchableCustomAttributes = [
[
'raw_sql_fragment' => "CONCAT(public.tbl_ort.ort_kurzbz, ' - ', public.tbl_ort.bezeichnung)",
'filter_parameter' => 'ort_kurzbz_bezeichnung_concat',
],
[
'raw_sql_fragment' => "CONCAT('[', org.organisationseinheittyp_kurzbz, '] ', org.bezeichnung)",
'filter_parameter' => 'org_organisationseinheittyp_kurzbz_org_bezeichnung_concat',
]
];
foreach ($searchableIdAttributes as $attribute) {
if (isset($filter[$attribute]) && $filter[$attribute] !== '') {
@@ -128,11 +143,45 @@ class Ort extends FHCAPI_Controller
}
}
foreach ($searchableCustomAttributes as $customAttribute) {
if (isset($filter[$customAttribute['filter_parameter']]) && $filter[$customAttribute['filter_parameter']] !== '') {
$queryWhereFragments[] = $customAttribute['raw_sql_fragment'] . " ILIKE ?";
$filterData[] = '%' . trim($filter[$customAttribute['filter_parameter']]) . '%';
}
}
if (count($queryWhereFragments) > 0) {
$query .= ' WHERE ' . implode(' AND ', $queryWhereFragments);
}
$query .= ' ORDER BY public.tbl_ort.ort_kurzbz ASC';
$sortableAttributes = ['ort_kurzbz', 'bezeichnung', 'planbezeichnung', 'max_person', 'arbeitsplaetze', 'm2', 'lehre', 'reservieren', 'aktiv', 'stockwerk', 'kosten', 'parent_ort_kurzbz', 'org_bezeichnung'];
$sortableConcatAttributes = [
[
'raw_sql_fragment' => "CONCAT('[', org.organisationseinheittyp_kurzbz, '] ', org.bezeichnung)",
'sort_parameter' => 'org_organisationseinheittyp_kurzbz_org_bezeichnung_concat',
]
];
$sorter = $this->input->get('sort', TRUE);
foreach ($sortableAttributes as $attribute) {
if (isset($sorter[$attribute]) && in_array(strtolower($sorter[$attribute]), ['asc', 'desc'])) {
if ($attribute === 'org_bezeichnung') {
$query .= " ORDER BY org.bezeichnung " . strtoupper($sorter[$attribute]);
} else {
$query .= " ORDER BY public.tbl_ort.$attribute " . strtoupper($sorter[$attribute]);
}
}
}
foreach ($sortableConcatAttributes as $customAttribute) {
if (isset($sorter[$customAttribute['sort_parameter']]) && in_array(strtolower($sorter[$customAttribute['sort_parameter']]), ['asc', 'desc'])) {
$query .= " ORDER BY " . $customAttribute['raw_sql_fragment'] . " " . strtoupper($sorter[$customAttribute['sort_parameter']]);
}
}
if (!isset($sorter)) {
$query .= ' ORDER BY public.tbl_ort.ort_kurzbz ASC';
}
if ($paginationSize && $paginationPage) {
$query .= " LIMIT ? OFFSET ?";
@@ -298,49 +347,10 @@ class Ort extends FHCAPI_Controller
public function createRoom()
{
$this->form_validation->set_rules('ort_kurzbz', 'kurzbezeichnung', 'required|is_unique[tbl_ort.ort_kurzbz]', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'kurzbz')]),
'is_unique' => $this->p->t('ui', 'error_fieldUnique', ['field' => $this->p->t('lehre', 'kurzbz')])
]);
$this->form_validation->set_rules('content_id', 'content_id', 'number', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'content_id')])
]);
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
$parent_ort_kurzbz = $this->input->post('parent_ort_kurzbz');
if ($parent_ort_kurzbz) {
$this->load->model('ressource/Ort_model', 'ParentRoomModel');
$parentRoom = $this->ParentRoomModel->load($parent_ort_kurzbz);
if (isError($parentRoom) || !hasData($parentRoom)) {
$this->terminateWithError("Parent room with shortcode $parent_ort_kurzbz does not exist", self::ERROR_TYPE_GENERAL);
}
}
$oe_kurzbz = $this->input->post('oe_kurzbz');
if ($oe_kurzbz) {
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
$orgUnit = $this->OrganisationseinheitModel->load($oe_kurzbz);
if (isError($orgUnit) || !hasData($orgUnit)) {
$this->terminateWithError("Organizational unit with shortcode $oe_kurzbz does not exist", self::ERROR_TYPE_GENERAL);
}
}
$standort_id = $this->input->post('standort_id');
if ($standort_id) {
$this->load->model('organisation/Standort_model', 'StandortModel');
$location = $this->StandortModel->load($standort_id);
if (isError($location) || !hasData($location)) {
$this->terminateWithError("Location with id $standort_id does not exist", self::ERROR_TYPE_GENERAL);
}
}
$content_id = $this->input->post('content_id');
if ($content_id) {
$this->load->model('content/Content_model', 'ContentModel');
$content = $this->ContentModel->load($content_id);
if (isError($content) || !hasData($content)) {
$this->terminateWithError("Content with id $content_id does not exist", self::ERROR_TYPE_GENERAL);
}
if (!$this->roomrequest->validate()) {
$this->terminateWithValidationErrors($this->roomrequest->errors());
return;
}
$this->db->trans_start();
@@ -365,7 +375,7 @@ class Ort extends FHCAPI_Controller
"telefonklappe" => $this->input->post('telefonklappe'),
"m2" => $this->input->post('m2'),
"gebteil" => $this->input->post('gebteil'),
"arbeitsplaetze" => $this->input->post('arbeitsplatze'),
"arbeitsplaetze" => $this->input->post('arbeitsplaetze'),
'insertamum' => date('c'),
'insertvon' => getAuthUid(),
'updateamum' => date('c'),
@@ -383,44 +393,9 @@ class Ort extends FHCAPI_Controller
public function updateRoom($ort_kurzbz)
{
if (!$ort_kurzbz) {
$this->terminateWithError("missing ort_kurzbz parameter", self::ERROR_TYPE_GENERAL);
}
$parent_ort_kurzbz = $this->input->post('parent_ort_kurzbz');
if ($parent_ort_kurzbz) {
$this->load->model('ressource/Ort_model', 'ParentRoomModel');
$parentRoom = $this->ParentRoomModel->load($parent_ort_kurzbz);
if (isError($parentRoom) || !hasData($parentRoom)) {
$this->terminateWithError("Parent room with shortcode $parent_ort_kurzbz does not exist", self::ERROR_TYPE_GENERAL);
}
}
$oe_kurzbz = $this->input->post('oe_kurzbz');
if ($oe_kurzbz) {
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
$orgUnit = $this->OrganisationseinheitModel->load($oe_kurzbz);
if (isError($orgUnit) || !hasData($orgUnit)) {
$this->terminateWithError("Organizational unit with shortcode $oe_kurzbz does not exist", self::ERROR_TYPE_GENERAL);
}
}
$standort_id = $this->input->post('standort_id');
if ($standort_id) {
$this->load->model('organisation/Standort_model', 'StandortModel');
$location = $this->StandortModel->load($standort_id);
if (isError($location) || !hasData($location)) {
$this->terminateWithError("Location with id $standort_id does not exist", self::ERROR_TYPE_GENERAL);
}
}
$content_id = $this->input->post('content_id');
if ($content_id) {
$this->load->model('content/Content_model', 'ContentModel');
$content = $this->ContentModel->load($content_id);
if (isError($content) || !hasData($content)) {
$this->terminateWithError("Content with id $content_id does not exist", self::ERROR_TYPE_GENERAL);
}
if (!$this->roomrequest->validate("update")) {
$this->terminateWithValidationErrors($this->roomrequest->errors());
return;
}
$this->db->trans_start();
@@ -0,0 +1,104 @@
<?php
/**
* FH-Complete
*
* @package FHC-Helper
* @author FHC-Team
* @copyright Copyright (c) 2022 fhcomplete.net
* @license GPLv3
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
class CustomFormValidationLib extends CI_Form_validation
{
public function __construct($rules = array())
{
parent::__construct($rules);
$this->_ci =& get_instance();
}
function explicit_integer($value)
{
if ($value === null) {
return true;
}
if ($value === '') {
return false;
}
if (filter_var($value, FILTER_VALIDATE_INT) !== false) {
return true;
}
return false;
}
function explicit_numeric($value)
{
if ($value === null) {
return true;
}
if ($value === '') {
return false;
}
if (is_numeric($value)) {
return true;
}
return false;
}
function explicit_boolean($value)
{
if ($value === null) {
return true;
}
if ($value === '') {
return false;
}
if ($value === 'true' || $value === 'false' || $value === true || $value === false || $value === 1 || $value === 0) {
return true;
}
return false;
}
function does_exist($value, $params)
{
if ($value === null ) {
return true;
}
if ($value === '') {
return false;
}
$parts = explode('.', $params);
if (count($parts) !== 3) {
return false;
}
$subDatabase = $parts[0];
$table = $parts[1];
$field = $parts[2];
$result = $this->_ci->db->select('COUNT(*) as count')
->from("$subDatabase.$table")
->where($field, $value)
->get();
if ($result === false) {
return false;
}
return $result->row()->count > 0;
}
}
@@ -0,0 +1,92 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class RoomRequest
{
protected $_ci;
public function __construct()
{
$this->_ci =& get_instance();
$this->_ci->load->library('CustomFormValidationLib');
}
public function validate($method = 'create')
{
if ($method === 'create') {
$this->_ci->customformvalidationlib->set_rules('ort_kurzbz', 'kurzbezeichnung', 'required|is_unique[tbl_ort.ort_kurzbz]|max_length[16]|regex_match[/^[a-zA-Z0-9_.]+$/]', [
'required' => $this->_ci->p->t('ui', 'error_fieldRequired', ['field' => $this->_ci->p->t('gruppenmanagement', 'kurzbezeichnung')]),
'is_unique' => $this->_ci->p->t('ui', 'error_fieldUnique', ['field' => $this->_ci->p->t('gruppenmanagement', 'kurzbezeichnung')]),
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('gruppenmanagement', 'kurzbezeichnung'), 'max' => 16]),
'regex_match' => $this->_ci->p->t('ui', 'error_fieldInvalidFormat', ['field' => $this->_ci->p->t('gruppenmanagement', 'kurzbezeichnung')])
]);
}
$this->_ci->customformvalidationlib->set_rules('parent_ort_kurzbz', 'parent_ort_kurzbz', 'does_exist[public.tbl_ort.ort_kurzbz]|max_length[16]', [
'does_exist' => $this->_ci->p->t('ui', 'error_entryDoesExists', ['entry' => $this->_ci->p->t('ui', 'parentRoom')]),
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('ui', 'parentRoom'), 'max' => 16])
]);
$this->_ci->customformvalidationlib->set_rules('oe_kurzbz', 'oe_kurzbz', 'does_exist[public.tbl_organisationseinheit.oe_kurzbz]|max_length[32]', [
'does_exist' => $this->_ci->p->t('ui', 'error_entryDoesExists', ['entry' => $this->_ci->p->t('lehre', 'organisationseinheit')]),
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('lehre', 'organisationseinheit'), 'max' => 32])
]);
$this->_ci->customformvalidationlib->set_rules('standort_id', 'standort_id', 'explicit_integer|does_exist[public.tbl_standort.standort_id]', [
'does_exist' => $this->_ci->p->t('ui', 'error_entryDoesExists', ['entry' => $this->_ci->p->t('person', 'standort')]),
]);
$this->_ci->customformvalidationlib->set_rules('content_id', 'content_id', 'explicit_integer|does_exist[campus.tbl_content.content_id]', [
'explicit_integer' => $this->_ci->p->t('ui', 'error_fieldInteger', ['field' => $this->_ci->p->t('ui', 'contentId')]),
'does_exist' => $this->_ci->p->t('ui', 'error_entryDoesExists', ['entry' => $this->_ci->p->t('ui', 'contentId')])
]);
$this->_ci->customformvalidationlib->set_rules('lehre', 'lehre', 'explicit_boolean', [
'explicit_boolean' => $this->_ci->p->t('ui', 'error_fieldBoolean', ['field' => $this->_ci->p->t('ui', 'lehre')])
]);
$this->_ci->customformvalidationlib->set_rules('reservieren', 'reservieren', 'explicit_boolean', [
'explicit_boolean' => $this->_ci->p->t('ui', 'error_fieldBoolean', ['field' => $this->_ci->p->t('ui', 'reservieren')])
]);
$this->_ci->customformvalidationlib->set_rules('aktiv', 'aktiv', 'explicit_boolean', [
'explicit_boolean' => $this->_ci->p->t('ui', 'error_fieldBoolean', ['field' => $this->_ci->p->t('person', 'aktiv')])
]);
$this->_ci->customformvalidationlib->set_rules('bezeichnung', 'bezeichnung', 'max_length[64]', [
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('ui', 'bezeichnung'), 'max' => 64])
]);
$this->_ci->customformvalidationlib->set_rules('planbezeichnung', 'planbezeichnung', 'max_length[8]', [
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('ui', 'planbezeichnung'), 'max' => 8])
]);
$this->_ci->customformvalidationlib->set_rules('max_person', 'maxPerson', 'explicit_integer', [
'explicit_integer' => $this->_ci->p->t('ui', 'error_fieldInteger', ['field' => $this->_ci->p->t('ui', 'maxPersons')])
]);
$this->_ci->customformvalidationlib->set_rules('stockwerk', 'stockwerk', 'explicit_integer', [
'explicit_integer' => $this->_ci->p->t('ui', 'error_fieldInteger', ['field' => $this->_ci->p->t('ui', 'stockwerk')])
]);
$this->_ci->customformvalidationlib->set_rules('m2', 'm2', 'explicit_numeric', [
'explicit_numeric' => $this->_ci->p->t('ui', 'error_fieldNumeric', ['field' => $this->_ci->p->t('ui', 'quadratmeter')])
]);
$this->_ci->customformvalidationlib->set_rules('dislozierung', 'dislozierung', 'explicit_numeric', [
'explicit_numeric' => $this->_ci->p->t('ui', 'error_fieldNumeric', ['field' => $this->_ci->p->t('ui', 'dislozierung')])
]);
$this->_ci->customformvalidationlib->set_rules('kosten', 'kosten', 'explicit_numeric', [
'explicit_numeric' => $this->_ci->p->t('ui', 'error_fieldNumeric', ['field' => $this->_ci->p->t('ui', 'kosten')])
]);
$this->_ci->customformvalidationlib->set_rules('telefonklappe', 'telefonklappe', 'max_length[8]', [
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('person', 'telefonklappe'), 'max' => 8])
]);
$this->_ci->customformvalidationlib->set_rules('gebteil', 'gebteil', 'max_length[32]', [
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('ui', 'gebaudeteil'), 'max' => 32])
]);
$this->_ci->customformvalidationlib->set_rules('arbeitsplaetze', 'arbeitsplaetze', 'explicit_integer', [
'explicit_integer' => $this->_ci->p->t('ui', 'error_fieldInteger', ['field' => $this->_ci->p->t('ui', 'arbeitsplaetze')])
]);
return $this->_ci->customformvalidationlib->run();
}
public function errors()
{
return $this->_ci->customformvalidationlib->error_array();
}
}
+38
View File
@@ -1,3 +1,41 @@
html {
font-size: .75em;
}
nav.navbar.navbar-header,
nav.navbar.navbar-left-side {
font-size: 18px
}
nav.navbar.navbar-left-side {
padding-top: 8px;
padding-bottom: 8px;
}
/* Relative sizing inside navbar */
nav.navbar .nav-item {
font-size: 18px
}
nav.navbar .navbar-brand-icon {
font-size: 16px
}
nav.navbar .left-side-menu-link-entry {
font-size: 14px !important;
}
nav.navbar .nav-link {
font-size: 18px;
padding-top: 15px;
padding-bottom: 8px;
}
nav.navbar .dropdown-menu {
padding: 8px 0px;
}
nav.navbar .dropdown-item {
font-size: 16px;
padding: 4px 16px;
}
+15 -1
View File
@@ -34,10 +34,24 @@ export default {
"filter[max_person]" : params?.maxPersons,
"filter[arbeitsplaetze]" : params?.workplace,
"filter[m2]" : params?.squareMeters,
"filter[oe_bezeichnung]" : params?.orgUnitDescription,
"filter[org_organisationseinheittyp_kurzbz_org_bezeichnung_concat]" : params?.orgUnitConcatDescription,
"filter[kosten]" : params?.costs,
"filter[stockwerk]" : params?.floor,
"filter[parent_ort_kurzbz]" : params?.parentRoomShortCode,
"filter[ort_kurzbz_bezeichnung_concat]" : params?.ort_kurzbz_bezeichnung_concat,
"sort[ort_kurzbz]" : params?.sort?.ort_kurzbz,
"sort[bezeichnung]" : params?.sort?.bezeichnung,
"sort[planbezeichnung]" : params?.sort?.planbezeichnung,
"sort[max_person]" : params?.sort?.max_person,
"sort[arbeitsplaetze]" : params?.sort?.arbeitsplaetze,
"sort[m2]" : params?.sort?.m2,
"sort[org_organisationseinheittyp_kurzbz_org_bezeichnung_concat]" : params?.sort?.org_organisationseinheittyp_kurzbz_org_bezeichnung_concat,
"sort[lehre]" : params?.sort?.lehre,
"sort[reservieren]" : params?.sort?.reservieren,
"sort[aktiv]" : params?.sort?.aktiv,
"sort[kosten]" : params?.sort?.kosten,
"sort[stockwerk]" : params?.sort?.stockwerk,
"sort[parent_ort_kurzbz]" : params?.sort?.parent_ort_kurzbz,
"pagination[page]" : params?.pagination?.page,
"pagination[size]" : params?.pagination?.size,
}
+105 -59
View File
@@ -38,7 +38,7 @@ export default {
} else {
this.resetRoomForm();
}
},
},
},
data: () => {
return {
@@ -65,8 +65,13 @@ export default {
},
dropdownParsedRooms() {
return this.rooms.map((room) => {
let label = room.ort_kurzbz;
if (room.bezeichnung && room.bezeichnung !== '') {
label += ` - ${room.bezeichnung}`;
}
return {
label: `${room.ort_kurzbz} - ${room.bezeichnung}`,
label,
value: room.ort_kurzbz,
};
});
@@ -75,7 +80,7 @@ export default {
methods: {
filterOrganizationalUnits(event) {
let defaultItem = {
label: "----------",
label: this.$p.t("ui", "dropdownEmptyOption"),
value: null,
};
@@ -97,7 +102,7 @@ export default {
this.rooms = await this.fetchRooms(event.query);
let defaultItem = {
label: "----------",
label: this.$p.t("ui", "dropdownEmptyOption"),
value: null,
};
@@ -149,7 +154,9 @@ export default {
};
}
let potentialParentRooms = await this.fetchRooms(this.editedRoom.parent_ort_kurzbz);
let potentialParentRooms = await this.fetchRooms(
this.editedRoom.parent_ort_kurzbz,
);
let parentRoomData = null;
let parentRoom = potentialParentRooms.find(
@@ -157,8 +164,13 @@ export default {
);
if (parentRoom) {
this.rooms.push(parentRoom);
let label = parentRoom.ort_kurzbz;
if (parentRoom.bezeichnung && parentRoom.bezeichnung !== '') {
label += ` - ${parentRoom.bezeichnung}`;
}
parentRoomData = {
label: `${parentRoom.ort_kurzbz} - ${parentRoom.bezeichnung}`,
label,
value: parentRoom.ort_kurzbz,
};
}
@@ -183,7 +195,7 @@ export default {
telefonklappe: this.editedRoom.telefonklappe,
quadratmeter: this.editedRoom.m2,
gebaudeteil: this.editedRoom.gebteil,
arbeitsplatze: this.editedRoom.arbeitsplaetze,
arbeitsplaetze: this.editedRoom.arbeitsplaetze,
};
this.$refs.roomFormModal.show();
@@ -207,24 +219,46 @@ export default {
return {
parent_ort_kurzbz: this.roomFormData.parentRoom?.value,
standort_id: this.roomFormData.locationId,
oe_kurzbz: this.roomFormData.organizationalUnit?.value,
content_id: this.roomFormData.contentId,
oe_kurzbz:
this.roomFormData.organizationalUnit?.value !== ""
? this.roomFormData.organizationalUnit?.value
: null,
content_id:
this.roomFormData.contentId !== ""
? this.roomFormData.contentId
: null,
ort_kurzbz: this.roomFormData.kurzbezeichnung,
bezeichnung: this.roomFormData.bezeichnung,
planbezeichnung: this.roomFormData.planbezeichnung,
aktiv: this.roomFormData.aktiv,
lehre: this.roomFormData.lehre,
reservieren: this.roomFormData.reservieren,
max_person: this.roomFormData.maxPerson,
stockwerk: this.roomFormData.stockwerk,
max_person:
this.roomFormData.maxPerson !== ""
? this.roomFormData.maxPerson
: null,
stockwerk:
this.roomFormData.stockwerk !== ""
? this.roomFormData.stockwerk
: null,
lageplan: this.roomFormData.lageplan,
dislozierung: this.roomFormData.dislozierung,
kosten: this.roomFormData.kosten,
dislozierung:
this.roomFormData.dislozierung === ""
? null
: this.roomFormData.dislozierung,
kosten:
this.roomFormData.kosten !== "" ? this.roomFormData.kosten : null,
ausstattung: this.roomFormData.ausstattung,
telefonklappe: this.roomFormData.telefonklappe,
m2: this.roomFormData.quadratmeter,
m2:
this.roomFormData.quadratmeter !== ""
? this.roomFormData.quadratmeter
: null,
gebteil: this.roomFormData.gebaudeteil,
arbeitsplatze: this.roomFormData.arbeitsplatze,
arbeitsplaetze:
this.roomFormData.arbeitsplaetze !== ""
? this.roomFormData.arbeitsplaetze
: null,
};
},
hideRoomFormModal() {
@@ -240,14 +274,16 @@ export default {
aktiv: true,
};
},
async fetchRooms(searchedRoomShortCode) {
let getRoomsResponse = await this.$api.call(ApiRoom.getAllRooms({
shortCode: searchedRoomShortCode,
pagination: {
page: 1,
size: 100,
},
}));
async fetchRooms(roomSearchTerm = "") {
let getRoomsResponse = await this.$api.call(
ApiRoom.getAllRooms({
ort_kurzbz_bezeichnung_concat: roomSearchTerm,
pagination: {
page: 1,
size: 100,
},
}),
);
if (getRoomsResponse.meta.status === "success") {
return getRoomsResponse.data;
} else {
@@ -256,6 +292,12 @@ export default {
return [];
},
setDefaultLocationOption() {
this.locations.unshift({
standort_id: null,
bezeichnung: this.$p.t("ui", "dropdownEmptyOption"),
});
},
},
async created() {
let getLocationsResponse = await this.$api.call(
@@ -263,10 +305,6 @@ export default {
);
if (getLocationsResponse.meta.status === "success") {
this.locations = getLocationsResponse.data;
this.locations.unshift({
standort_id: null,
kurzbz: "----------",
});
} else {
this.$fhcAlert.alertError(this.$p.t("ui", "errorLoadingLocations"));
}
@@ -285,6 +323,21 @@ export default {
}
this.rooms = await this.fetchRooms();
},
mounted() {
this.$p
.loadCategory([
"global",
"lehre",
"ui",
"gruppenmanagement",
"core",
"person",
])
.then(() => {
this.phrasesLoaded = true;
this.setDefaultLocationOption();
});
},
template: /* html */ `
<bs-modal ref="roomFormModal" size="sm" @hideBsModal="() => { $emit('hideBsModal'); resetRoomForm(); }" class="modal-lg">
@@ -306,7 +359,7 @@ export default {
dropdown
forceSelection
type="autocomplete"
name="parentRoomShortCode"
name="parent_ort_kurzbz"
>
</form-input>
</div>
@@ -322,38 +375,29 @@ export default {
dropdown
forceSelection
type="autocomplete"
name="organizationalUnitShortCode"
name="oe_kurzbz"
>
</form-input>
</div>
<div class="col">
<form-input
v-model="roomFormData.locationId"
:label="$capitalize($p.t('global/ortLocation'))"
:label="$capitalize($p.t('person/standort'))"
type="select"
id="location"
name="location"
name="standort_id"
>
<option
v-for="location in locations"
:key="location.standort_id"
:value="location.standort_id"
>
{{location.kurzbz}}
{{location.bezeichnung}}
</option>
</form-input>
</div>
</div>
<div class="row mb-3">
<div class="col">
<form-input
v-model="roomFormData.aktiv"
:label="$capitalize($p.t('person', 'aktiv'))"
type="checkbox"
name="aktiv"
>
</form-input>
</div>
<div class="col">
<form-input
v-model="roomFormData.lehre"
@@ -372,6 +416,15 @@ export default {
>
</form-input>
</div>
<div class="col">
<form-input
v-model="roomFormData.aktiv"
:label="$capitalize($p.t('person', 'aktiv'))"
type="checkbox"
name="aktiv"
>
</form-input>
</div>
</div>
<div v-if='!this.editedRoom' class="row mb-3">
<form-input
@@ -403,28 +456,25 @@ export default {
<div class="row mb-3">
<div class="col">
<form-input
v-model="roomFormData.maxPerson"
v-model.number="roomFormData.maxPerson"
:label="$capitalize($p.t('ui', 'maxPersons'))"
type="number"
name="maxPerson"
name="max_person"
>
</form-input>
</div>
<div class="col">
<form-input
v-model="roomFormData.stockwerk"
v-model.number="roomFormData.stockwerk"
:label="$capitalize($p.t('ui', 'stockwerk'))"
type="number"
name="stockwerk"
>
</form-input>
</div>
<div class="col">
<form-input
v-model="roomFormData.quadratmeter"
v-model.number="roomFormData.quadratmeter"
:label="$capitalize($p.t('ui', 'quadratmeter'))"
type="number"
name="quadratmeter"
name="m2"
>
</form-input>
</div>
@@ -434,17 +484,15 @@ export default {
<form-input
v-model="roomFormData.telefonklappe"
:label="$capitalize($p.t('person', 'telefonklappe'))"
type="number"
name="telefonklappe"
>
</form-input>
</div>
<div class='col'>
<form-input
v-model="roomFormData.arbeitsplatze"
v-model.number="roomFormData.arbeitsplaetze"
:label="$capitalize($p.t('ui', 'arbeitsplaetze'))"
type="number"
name="arbeitsplatze"
name="arbeitsplaetze"
>
</form-input>
</div>
@@ -464,24 +512,22 @@ export default {
v-model="roomFormData.gebaudeteil"
:label="$capitalize($p.t('ui', 'gebaudeteil'))"
type="text"
name="gebaudeteil"
name="gebteil"
>
</form-input>
</div>
<div class='col'>
<form-input
v-model="roomFormData.contentId"
v-model.number="roomFormData.contentId"
:label="$capitalize($p.t('ui', 'contentId'))"
type="number"
name="contentId"
name="content_id"
>
</form-input>
</div>
<div class='col'>
<form-input
v-model="roomFormData.dislozierung"
v-model.number="roomFormData.dislozierung"
:label="$capitalize($p.t('ui', 'dislozierung'))"
type="text"
name="dislozierung"
>
</form-input>
@@ -23,8 +23,7 @@ export default {
provide() {
return {
cisRoot: this.cisRoot,
hasBasisOrtWPermission:
this.permissions["basis/ort_w"] || false,
hasBasisOrtWPermission: this.permissions["basis/ort_w"] || false,
};
},
watch: {
@@ -50,14 +49,10 @@ export default {
organizationalUnits: [],
filteredOrganizationalUnits: [],
buildingComponents: [
{
label: "----------",
value: null,
},
{
label: "A",
value: "A",
},
},
{
label: "B",
value: "B",
@@ -67,16 +62,16 @@ export default {
value: "C",
},
{
label: "D",
value: "D"
label: "D",
value: "D",
},
{
label: "E",
value: "E"
value: "E",
},
{
label: "F",
value: "F"
value: "F",
},
],
isRoomFormModalVisible: false,
@@ -93,19 +88,45 @@ export default {
const options = {
ajaxURL: "dummy",
ajaxRequestFunc: async (url, config, params) => {
let shortCodeFilter = params?.filter?.find((filter) => filter.field === "ort_kurzbz");
let descriptionFilter = params?.filter?.find((filter) => filter.field === "bezeichnung");
let planDescriptionFilter = params?.filter?.find((filter) => filter.field === "planbezeichnung");
let maxPersonsFilter = params?.filter?.find((filter) => filter.field === "max_person");
let workplaceFilter = params?.filter?.find((filter) => filter.field === "arbeitsplaetze");
let squareMetersFilter = params?.filter?.find((filter) => filter.field === "m2");
let orgUnitFilter = params?.filter?.find((filter) => filter.field === "org_bezeichnung");
let isForTrainingProgramFilter = params?.filter?.find((filter) => filter.field === "lehre");
let reservationNeededFilter = params?.filter?.find((filter) => filter.field === "reservieren");
let isActiveFilter = params?.filter?.find((filter) => filter.field === "aktiv");
let costsFilter = params?.filter?.find((filter) => filter.field === "kosten");
let floorFilter = params?.filter?.find((filter) => filter.field === "stockwerk");
let parentRoomFilter = params?.filter?.find((filter) => filter.field === "pr_ort_kurzbz");
let shortCodeFilter = params?.filter?.find(
(filter) => filter.field === "ort_kurzbz",
);
let descriptionFilter = params?.filter?.find(
(filter) => filter.field === "bezeichnung",
);
let planDescriptionFilter = params?.filter?.find(
(filter) => filter.field === "planbezeichnung",
);
let maxPersonsFilter = params?.filter?.find(
(filter) => filter.field === "max_person",
);
let workplaceFilter = params?.filter?.find(
(filter) => filter.field === "arbeitsplaetze",
);
let squareMetersFilter = params?.filter?.find(
(filter) => filter.field === "m2",
);
let orgUnitConcatFilter = params?.filter?.find(
(filter) => filter.field === "org_organisationseinheittyp_kurzbz_org_bezeichnung_concat",
);
let isForTrainingProgramFilter = params?.filter?.find(
(filter) => filter.field === "lehre",
);
let reservationNeededFilter = params?.filter?.find(
(filter) => filter.field === "reservieren",
);
let isActiveFilter = params?.filter?.find(
(filter) => filter.field === "aktiv",
);
let costsFilter = params?.filter?.find(
(filter) => filter.field === "kosten",
);
let floorFilter = params?.filter?.find(
(filter) => filter.field === "stockwerk",
);
let parentRoomFilter = params?.filter?.find(
(filter) => filter.field === "parent_ort_kurzbz",
);
let isForTrainingProgramValue = null;
if (this.filterData.isForTrainingProgram === true) {
@@ -117,7 +138,7 @@ export default {
isForTrainingProgramValue = false;
}
}
let reservationNeededValue = null;
if (this.filterData.isReservationNeeded === true) {
reservationNeededValue = true;
@@ -140,6 +161,20 @@ export default {
}
}
let shortCodeSorter = params?.sort?.find((sort) => sort.field === "ort_kurzbz");
let descriptionSorter = params?.sort?.find((sort) => sort.field === "bezeichnung");
let planDescriptionSorter = params?.sort?.find((sort) => sort.field === "planbezeichnung");
let maxPersonsSorter = params?.sort?.find((sort) => sort.field === "max_person");
let workplaceSorter = params?.sort?.find((sort) => sort.field === "arbeitsplaetze");
let squareMetersSorter = params?.sort?.find((sort) => sort.field === "m2");
let orgUnitConcatSorter = params?.sort?.find((sort) => sort.field === "org_organisationseinheittyp_kurzbz_org_bezeichnung_concat");
let lehreSorter = params?.sort?.find((sort) => sort.field === "lehre");
let reservierenSorter = params?.sort?.find((sort) => sort.field === "reservieren");
let aktivSorter = params?.sort?.find((sort) => sort.field === "aktiv");
let costsSorter = params?.sort?.find((sort) => sort.field === "kosten");
let floorSorter = params?.sort?.find((sort) => sort.field === "stockwerk");
let parentRoomSorter = params?.sort?.find((sort) => sort.field === "parent_ort_kurzbz");
return this.$api.call(
ApiRoom.getAllRooms({
organizationalUnitShortCode:
@@ -155,10 +190,25 @@ export default {
maxPersons: maxPersonsFilter?.value,
workplace: workplaceFilter?.value,
squareMeters: squareMetersFilter?.value,
orgUnitDescription: orgUnitFilter?.value,
orgUnitConcatDescription: orgUnitConcatFilter?.value,
costs: costsFilter?.value,
floor: floorFilter?.value,
parentRoomShortCode: parentRoomFilter?.value,
sort: {
ort_kurzbz: shortCodeSorter?.dir,
bezeichnung: descriptionSorter?.dir,
planbezeichnung: planDescriptionSorter?.dir,
max_person: maxPersonsSorter?.dir,
arbeitsplaetze: workplaceSorter?.dir,
m2: squareMetersSorter?.dir,
org_organisationseinheittyp_kurzbz_org_bezeichnung_concat: orgUnitConcatSorter?.dir,
lehre: lehreSorter?.dir,
reservieren: reservierenSorter?.dir,
aktiv: aktivSorter?.dir,
kosten: costsSorter?.dir,
stockwerk: floorSorter?.dir,
parent_ort_kurzbz: parentRoomSorter?.dir,
},
pagination: {
page: params.page,
size: params.size,
@@ -167,7 +217,7 @@ export default {
);
},
ajaxResponse: (url, params, response) => response,
persistenceID: "room_manager_overview_table1111222233333",
persistenceID: "room_manager_overview_table",
selectableRows: true,
index: "ort_kurzbz",
columns: [
@@ -209,11 +259,40 @@ export default {
title: this.$capitalize(this.$p.t("ui", "quadratmeter")),
field: "m2",
headerFilter: true,
width: 100
width: 100,
},
{
title: this.$capitalize(this.$p.t("lehre", "organisationseinheit")),
field: "org_bezeichnung",
field: "org_organisationseinheittyp_kurzbz_org_bezeichnung_concat",
formatter: function (cell) {
let data = cell.getRow().getData();
let value = null;
if (data.org_organisationseinheittyp_kurzbz) {
value = `[${data.org_organisationseinheittyp_kurzbz}]`;
}
if (data.org_bezeichnung) {
value += ` ${data.org_bezeichnung}`;
}
return value;
},
sorter: function (a, b, aRow, bRow, column, dir, sorterParams) {
let aData = aRow.getData();
let bData = bRow.getData();
let aFull = (
aData.org_organisationseinheittyp_kurzbz +
" " +
aData.org_bezeichnung
).toLowerCase().trim();
let bFull = (
bData.org_organisationseinheittyp_kurzbz +
" " +
bData.org_bezeichnung
).toLowerCase().trim();
return aFull.localeCompare(bFull);
},
headerFilter: true,
width: 180,
},
@@ -222,8 +301,9 @@ export default {
field: "lehre",
headerFilter: true,
headerFilterParams: {
"tristate":true, elementAttributes:{"value":"true"}
},
tristate: true,
elementAttributes: { value: "true" },
},
formatter: "tickCross",
hozAlign: "center",
formatterParams: {
@@ -236,8 +316,9 @@ export default {
field: "reservieren",
headerFilter: true,
headerFilterParams: {
"tristate":true, elementAttributes:{"value":"true"}
},
tristate: true,
elementAttributes: { value: "true" },
},
formatter: "tickCross",
hozAlign: "center",
formatterParams: {
@@ -250,8 +331,9 @@ export default {
field: "aktiv",
headerFilter: true,
headerFilterParams: {
"tristate":true, elementAttributes:{"value":"true"}
},
tristate: true,
elementAttributes: { value: "true" },
},
formatter: "tickCross",
hozAlign: "center",
formatterParams: {
@@ -271,7 +353,7 @@ export default {
},
{
title: this.$capitalize(this.$p.t("ui", "parentRoom")),
field: "pr_ort_kurzbz",
field: "parent_ort_kurzbz",
headerFilter: true,
width_: 120,
},
@@ -286,7 +368,9 @@ export default {
let roomTypeBtn = document.createElement("button");
roomTypeBtn.className = "btn btn-outline-secondary btn-action";
roomTypeBtn.innerHTML = '<i class="fa fa-layer-group"></i>';
roomTypeBtn.title = this.$capitalize(this.$p.t("ui", "btn_editRoomType"));
roomTypeBtn.title = this.$capitalize(
this.$p.t("ui", "btn_editRoomType"),
);
roomTypeBtn.addEventListener("click", (event) =>
this.editRoomType(cell.getData().ort_kurzbz),
);
@@ -294,7 +378,7 @@ export default {
if (!this.hasBasisOrtWPermission) {
container.append(roomTypeBtn);
return container;
}2222
}
let button = document.createElement("button");
@@ -313,7 +397,9 @@ export default {
button.className =
"btn btn-outline-secondary btn-action bg-danger";
button.innerHTML = '<i class="fa fa-xmark text-white"></i>';
button.title = this.$capitalize(this.$p.t("ui", "btn_deleteRoom"));
button.title = this.$capitalize(
this.$p.t("ui", "btn_deleteRoom"),
);
button.addEventListener("click", () => {
let isDeletionConfirmed = confirm(
this.$p.t("ui", "deleteRoomConfirmation"),
@@ -330,11 +416,12 @@ export default {
},
],
layout: "fitColumns",
pagination:true,
paginationMode:"remote",
pagination: true,
paginationMode: "remote",
paginationSize: 100,
maxHeight:"700px",
filterMode:"remote",
maxHeight: "700px",
filterMode: "remote",
sortMode: "remote",
};
return options;
},
@@ -371,18 +458,20 @@ export default {
return events;
},
dropdownParsedOrganizationalUnits() {
return this.organizationalUnits.map((unit) => {
return {
label: `${unit.bezeichnung} (${unit.organisationseinheittyp_kurzbz})`,
value: unit.oe_kurzbz,
};
});
return this.organizationalUnits
.map((unit) => {
return {
label: `[${unit.organisationseinheittyp_kurzbz}] ${unit.bezeichnung}`,
value: unit.oe_kurzbz,
};
})
.sort((a, b) => a.label.localeCompare(b.label));
},
},
methods: {
filterOrganizationalUnits(event) {
let defaultItem = {
label: "----------",
label: this.$p.t("ui", "dropdownEmptyOption"),
value: null,
};
@@ -450,6 +539,18 @@ export default {
this.$fhcAlert.alertError(this.$p.t("ui", "errorUpdatingRoom"));
}
},
setDefaultBuildingComponentOption() {
this.buildingComponents.unshift({
label: this.$p.t("ui", "dropdownEmptyOption"),
value: null,
});
},
setDefaultLocationOption() {
this.locations.unshift({
standort_id: null,
bezeichnung: this.$p.t("ui", "dropdownEmptyOption"),
});
},
},
async created() {
let getLocationsResponse = await this.$api.call(
@@ -457,7 +558,6 @@ export default {
);
if (getLocationsResponse.meta.status === "success") {
this.locations = getLocationsResponse.data;
this.locations.unshift({ standort_id: null, kurzbz: "----------" });
} else {
this.$fhcAlert.alertError(this.$p.t("ui", "errorLoadingLocations"));
}
@@ -470,7 +570,9 @@ export default {
(a, b) => a.bezeichnung.localeCompare(b.bezeichnung),
);
} else {
this.$fhcAlert.alertError(this.$p.t("ui", "errorLoadingOrganizationalUnits"));
this.$fhcAlert.alertError(
this.$p.t("ui", "errorLoadingOrganizationalUnits"),
);
}
},
mounted() {
@@ -485,6 +587,8 @@ export default {
])
.then(() => {
this.phrasesLoaded = true;
this.setDefaultBuildingComponentOption();
this.setDefaultLocationOption();
});
},
template: /* html */ `
@@ -524,7 +628,7 @@ export default {
<div>
<form-input
v-model="filterData.locationId"
:label="$capitalize($p.t('global', 'raum'))"
:label="$capitalize($p.t('person', 'standort'))"
type="select"
id="location"
name="location"
@@ -534,7 +638,7 @@ export default {
:key="location.standort_id"
:value="location.standort_id"
>
{{location.kurzbz}}
{{location.bezeichnung}}
</option>
</form-input>
</div>
@@ -156,7 +156,7 @@ export default {
methods: {
filterRoomTypes(event) {
let defaultItem = {
label: "----------",
label: this.$p.t("ui", "dropdownEmptyOption"),
value: null,
};
+147
View File
@@ -59077,6 +59077,153 @@ I have been informed that I am under no obligation to consent to the transmissio
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'error_fieldMaxLength',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Das Eingabefeld {field} überschreitet die maximale Länge von {max} Zeichen',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'The Input Field {field} exceeds the maximum length of {max} characters',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'error_fieldInteger',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Das Eingabefeld {field} muss eine ganze Zahl sein',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'The Input Field {field} must be an integer',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'error_fieldNumeric',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Das Eingabefeld {field} muss eine Zahl sein',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'The Input Field {field} must be a number',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'error_entryDoesExists',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Der Eintrag in der DB mit diesem {entry} existiert nicht',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'The entry in DB with this {entry} does not exist',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'error_fieldBoolean',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Das Eingabefeld {field} muss ein Wahrheitswert sein',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'The Input Field {field} must be a boolean value',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'error_fieldInvalidFormat',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Das Eingabefeld {field} hat ein ungültiges Format',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'The Input Field {field} has an invalid format',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'dropdownEmptyOption',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => '--keine Auswahl--',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => '--no selection--',
'description' => '',
'insertvon' => 'system'
)
)
),
);