diff --git a/application/config/routes.php b/application/config/routes.php
index aa4ba9db8..3462113f9 100644
--- a/application/config/routes.php
+++ b/application/config/routes.php
@@ -122,6 +122,8 @@ $route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/person/(:num)'] = 'api/f
// load routes from extensions, also look for environment-specific configs
$subdirs = ['application/config/extensions', 'application/config/' . ENVIRONMENT . '/extensions'];
+$route['lehre/RoomManager/.*'] = 'lehre/RoomManager/index';
+
foreach($subdirs as $subdir)
{
if(is_dir($subdir))
diff --git a/application/controllers/RoomManager.php b/application/controllers/RoomManager.php
new file mode 100644
index 000000000..9591f5f36
--- /dev/null
+++ b/application/controllers/RoomManager.php
@@ -0,0 +1,60 @@
+ array('lehre/unterrichtszeiten_gk:r'),
+ )
+ );
+
+ $this->load->library('PermissionLib');
+ $this->load->library('AuthLib');
+
+ $this->loadPhrases(
+ array(
+ 'ui',
+ 'global',
+ 'person',
+ 'abschlusspruefung',
+ 'password',
+ 'lehre'
+ )
+ );
+
+ $this->_setAuthUID();
+
+ $this->setControllerId();
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+ // Public methods
+ public function index()
+ {
+ return $this->load->view('room_manager/index');
+ }
+
+ // -----------------------------------------------------------------------------------------------------------------
+ // Private methods
+
+ /**
+ * Retrieve the UID of the logged user and checks if it is valid
+ */
+ private function _setAuthUID()
+ {
+ $this->_uid = getAuthUID();
+
+ if (!$this->_uid) show_error('User authentification failed');
+ }
+}
\ No newline at end of file
diff --git a/application/controllers/api/frontend/v1/Ort.php b/application/controllers/api/frontend/v1/Ort.php
index 0d8074fa9..c8fee5b72 100644
--- a/application/controllers/api/frontend/v1/Ort.php
+++ b/application/controllers/api/frontend/v1/Ort.php
@@ -33,19 +33,63 @@ class Ort extends FHCAPI_Controller
{
// NOTE(chris): additional permission checks will be done in SearchBarLib
parent::__construct([
+ 'getAllRooms' => self::PERM_LOGGED,
+ 'getRooms' => self::PERM_LOGGED,
+ 'getTypes' => self::PERM_LOGGED,
'ContentID' => self::PERM_LOGGED,
'getOrtKurzbzContent' => self::PERM_LOGGED,
- 'getRooms' => self::PERM_LOGGED,
- 'getTypes' => self::PERM_LOGGED
+ 'getRoom' => self::PERM_LOGGED,
+ 'createRoom' => self::PERM_LOGGED,
+ 'updateRoom' => self::PERM_LOGGED,
+ 'deleteRoom' => self::PERM_LOGGED,
]);
+ $this->load->library('form_validation');
+
$this->load->model('ressource/Ort_model', 'OrtModel');
$this->config->load('raumsuche');
+
+ $this->loadPhrases([
+ 'global',
+ 'ui',
+ ]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
+ public function getAllRooms()
+ {
+ $filter = $this->input->get('filter', TRUE);
+
+ $filterData = [];
+
+ if (isset($filter['locationId']) && $filter['locationId'] !== '') {
+ $filterData['standort_id'] = $filter['locationId'];
+ }
+ if (isset($filter['organizationalUnitShortCode']) && $filter['organizationalUnitShortCode'] !== '') {
+ $filterData['oe_kurzbz'] = $filter['organizationalUnitShortCode'];
+ }
+ if (isset($filter['buildingComponent']) && $filter['buildingComponent'] !== '') {
+ $filterData['gebteil'] = $filter['buildingComponent'];
+ }
+ if (isset($filter['isForTrainingProgram']) && $filter['isForTrainingProgram'] === 'true') {
+ $filterData['lehre'] = $filter['isForTrainingProgram'] === 'true' ? true : false;
+ }
+ if (isset($filter['isReservationNeeded']) && $filter['isReservationNeeded'] === 'true') {
+ $filterData['reservieren'] = $filter['isReservationNeeded'] === 'true' ? true : false;
+ }
+ if (isset($filter['isActive']) && $filter['isActive'] === 'true') {
+ $filterData['aktiv'] = $filter['isActive'] === 'true' ? true : false;
+ }
+
+ $this->OrtModel->addOrder("ort_kurzbz", "ASC");
+
+ $result = $this->OrtModel->loadWhere($filterData);
+
+ $this->terminateWithSuccess($this->getDataOrTerminateWithError($result));
+ }
+
/**
* Retrieves all Ort entries filtered by the provided parameters
*/
@@ -54,7 +98,7 @@ class Ort extends FHCAPI_Controller
$this->load->library('form_validation');
$this->form_validation->set_data($_GET);
$this->form_validation->set_rules('datum','Datum','required');
- $this->form_validation->set_rules('von','Uhrzeit Von','required|regex_match[/^[0-9]{2}:[0-9]{2}$/]');
+ $this->form_validation->set_rules('von','Uhrzeit Von','required|regexresponse_match[/^[0-9]{2}:[0-9]{2}$/]');
$this->form_validation->set_rules('bis','Uhrzeit Bis','required|regex_match[/^[0-9]{2}:[0-9]{2}$/]');
if($this->form_validation->run() == FALSE) {
$this->terminateWithValidationErrors($this->form_validation->error_array());
@@ -174,5 +218,163 @@ class Ort extends FHCAPI_Controller
$this->terminateWithSuccess($content);
}
+
+ public function getRoom($ort_kurzbz)
+ {
+ $result = $this->OrtModel->load($ort_kurzbz);
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+
+ $result = hasData($result) ? current(getData($result)) : null;
+
+ return $this->terminateWithSuccess($result);
+ }
+
+ public function createRoom()
+ {
+ $this->form_validation->set_rules('ort_kurzbz', 'ort_kurzbz', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('ui', 'shortCode')])
+ ]);
+
+ if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $this->db->trans_start();
+
+ $result = $this->OrtModel->db->query("INSERT INTO public.tbl_ort
+ (
+ oe_kurzbz,
+ content_id,
+ standort_id,
+ ort_kurzbz,
+ bezeichnung,
+ planbezeichnung,
+ aktiv,
+ lehre,
+ reservieren,
+ max_person,
+ stockwerk,
+ lageplan,
+ dislozierung,
+ kosten,
+ ausstattung,
+ telefonklappe,
+ m2,
+ gebteil,
+ arbeitsplaetze,
+ insertamum,
+ insertvon,
+ updateamum,
+ updatevon
+ )
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", [
+ $this->input->post('oe_kurzbz'),
+ $this->input->post('contentId'),
+ $this->input->post('standort_id'),
+ $this->input->post('ort_kurzbz'),
+ $this->input->post('bezeichnung'),
+ $this->input->post('planbezeichnung'),
+ $this->input->post('aktiv') ? true : false,
+ $this->input->post('lehre') ? true : false,
+ $this->input->post('reservieren') ? true : false,
+ $this->input->post('max_person'),
+ $this->input->post('stockwerk'),
+ $this->input->post('lageplan'),
+ $this->input->post('dislozierung'),
+ $this->input->post('kosten'),
+ $this->input->post('ausstattung'),
+ $this->input->post('telefonklappe'),
+ $this->input->post('m2'),
+ $this->input->post('gebteil'),
+ $this->input->post('arbeitsplatze'),
+ date('c'),
+ getAuthUid(),
+ date('c'),
+ getAuthUid()
+ ]);
+
+ $this->db->trans_complete();
+
+
+ return $this->terminateWithSuccess($result);
+ }
+
+ public function updateRoom($ort_kurzbz)
+ {
+ if (!$ort_kurzbz) {
+ $this->terminateWithError("missing ort_kurzbz parameter", self::ERROR_TYPE_GENERAL);
+ }
+
+ $this->db->trans_start();
+
+ $result = $this->OrtModel->db->query("UPDATE public.tbl_ort SET
+ oe_kurzbz = ?,
+ content_id = ?,
+ standort_id = ?,
+ bezeichnung = ?,
+ planbezeichnung = ?,
+ aktiv = ?,
+ lehre = ?,
+ reservieren = ?,
+ max_person = ?,
+ stockwerk = ?,
+ lageplan = ?,
+ dislozierung = ?,
+ kosten = ?,
+ ausstattung = ?,
+ telefonklappe = ?,
+ m2 = ?,
+ gebteil = ?,
+ arbeitsplaetze = ?,
+ updateamum = ?,
+ updatevon = ?
+ WHERE ort_kurzbz = ?", [
+ $this->input->post('oe_kurzbz'),
+ $this->input->post('contentId'),
+ $this->input->post('standort_id'),
+ $this->input->post('bezeichnung'),
+ $this->input->post('planbezeichnung'),
+ $this->input->post('aktiv') ? true : false,
+ $this->input->post('lehre') ? true : false,
+ $this->input->post('reservieren') ? true : false,
+ $this->input->post('max_person'),
+ $this->input->post('stockwerk'),
+ $this->input->post('lageplan'),
+ $this->input->post('dislozierung'),
+ $this->input->post('kosten'),
+ $this->input->post('ausstattung'),
+ $this->input->post('telefonklappe'),
+ $this->input->post('m2'),
+ $this->input->post('gebteil'),
+ $this->input->post('arbeitsplatze'),
+ date('c'),
+ getAuthUid(),
+ $ort_kurzbz
+ ]);
+
+ $this->db->trans_complete();
+
+
+ return $this->terminateWithSuccess($result);
+ }
+
+ public function deleteRoom($ort_kurzbz)
+ {
+
+ $this->db->trans_start();
+
+ $result = $this->OrtModel->delete([
+ "ort_kurzbz" => $ort_kurzbz
+ ]);
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+
+ $this->db->trans_complete();
+
+ return $this->terminateWithSuccess(true);
+ }
}
diff --git a/application/controllers/api/frontend/v1/organisation/LocationApi.php b/application/controllers/api/frontend/v1/organisation/LocationApi.php
new file mode 100644
index 000000000..8a5ac4f6e
--- /dev/null
+++ b/application/controllers/api/frontend/v1/organisation/LocationApi.php
@@ -0,0 +1,56 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+class LocationApi extends FHCAPI_Controller
+{
+
+ /**
+ * Object initialization
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'getLocationsByCompanyType'=> self::PERM_LOGGED,
+ ]);
+
+ $this->load->library('form_validation');
+
+ $this->load->model('organisation/standort_model', 'StandortModel');
+
+ $this->loadPhrases([
+ 'global',
+ 'ui',
+ ]);
+
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+ public function getLocationsByCompanyType() {
+ $companyType = $this->input->get('companyType');
+ if (!isset($companyType)) {
+ $this->terminateWithError('companyType parameter is required', REST_Controller::HTTP_BAD_REQUEST);
+ return;
+ }
+
+ $result = $this->StandortModel->getByCompanyType($companyType);
+
+ return $this->terminateWithSuccess($this->getDataOrTerminateWithError($result));
+ }
+}
\ No newline at end of file
diff --git a/application/controllers/api/frontend/v1/organisation/OrganizationalUnitApi.php b/application/controllers/api/frontend/v1/organisation/OrganizationalUnitApi.php
new file mode 100644
index 000000000..dce7c5222
--- /dev/null
+++ b/application/controllers/api/frontend/v1/organisation/OrganizationalUnitApi.php
@@ -0,0 +1,55 @@
+.
+ */
+
+if (! defined('BASEPATH')) exit('No direct script access allowed');
+class OrganizationalUnitApi extends FHCAPI_Controller
+{
+ /**
+ * Object initialization
+ */
+ public function __construct()
+ {
+ parent::__construct([
+ 'getAllOrganizationalUnits'=> array('basis/organisationseinheit:r'),
+ ]);
+
+ $this->load->library('form_validation');
+
+ $this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
+
+ $this->loadPhrases([
+ 'global'
+ ]);
+
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+
+ public function getAllOrganizationalUnits()
+ {
+ $entitledOrganizationalUnitsShortCodes = $this->permissionlib->getOE_isEntitledFor('basis/organisationseinheit');
+
+ $this->OrganisationseinheitModel->db->where_in('oe_kurzbz', $entitledOrganizationalUnitsShortCodes);
+ $result = $this->OrganisationseinheitModel->load();
+
+ $organization_units_result = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($organization_units_result);
+ }
+}
\ No newline at end of file
diff --git a/application/models/organisation/Standort_model.php b/application/models/organisation/Standort_model.php
index aeeab4497..0d5f157df 100644
--- a/application/models/organisation/Standort_model.php
+++ b/application/models/organisation/Standort_model.php
@@ -35,5 +35,15 @@ class Standort_model extends DB_Model
return $this->loadWhere(array("firma_id" => $firma_id));
}
+
+ public function getByCompanyType($companyType)
+ {
+ $query = "SELECT s.* FROM public.tbl_standort s
+ JOIN public.tbl_firma f ON s.firma_id = f.firma_id
+ JOIN public.tbl_adresse a ON s.adresse_id = a.adresse_id
+ WHERE f.firmentyp_kurzbz = ?;";
+
+ return $this->execReadOnlyQuery($query, [$companyType]);
+ }
}
diff --git a/application/views/room_manager/index.php b/application/views/room_manager/index.php
new file mode 100644
index 000000000..a355fa857
--- /dev/null
+++ b/application/views/room_manager/index.php
@@ -0,0 +1,39 @@
+ 'Raumverwaltung',
+ 'vue3' => true,
+ 'axios027' => true,
+ 'bootstrap5' => true,
+ 'tabulator5' => true,
+ 'fontawesome6' => true,
+ 'primevue3' => true,
+ 'navigationcomponent' => true,
+ 'filtercomponent' => true,
+ 'vuedatepicker11' => true,
+ 'customJSs' => array(
+ 'vendor/moment/luxonjs/luxon.min.js'
+ ),
+ 'customJSModules' => array(
+ 'public/js/apps/RoomManagerApp.js'
+ ),
+ 'customCSSs' => array(
+ 'public/css/components/primevue.css',
+ 'public/css/components/verticalsplit.css',
+ 'public/extensions/FHC-Core-Developer/css/FhcMain.css',
+ 'public/css/components/calendar.css',
+ 'public/css/components/vue-datepicker.css',
+ )
+);
+
+$this->load->view('templates/FHC-Header', $includesArray);
+?>
+
+
+
+
+
+
+
+load->view('templates/FHC-Footer', $includesArray); ?>
\ No newline at end of file
diff --git a/public/js/api/factory/location.js b/public/js/api/factory/location.js
new file mode 100644
index 000000000..35afcc305
--- /dev/null
+++ b/public/js/api/factory/location.js
@@ -0,0 +1,10 @@
+
+export default {
+ getLocationsByCompanyType(companyType) {
+ return {
+ method: 'get',
+ url: '/api/frontend/v1/organisation/LocationApi/getLocationsByCompanyType',
+ params: { companyType }
+ };
+ }
+};
\ No newline at end of file
diff --git a/public/js/api/factory/organizationalUnit.js b/public/js/api/factory/organizationalUnit.js
new file mode 100644
index 000000000..1c17ab5d1
--- /dev/null
+++ b/public/js/api/factory/organizationalUnit.js
@@ -0,0 +1,8 @@
+export default {
+ getAllOrganizationalUnits() {
+ return {
+ method: "get",
+ url: "api/frontend/v1/organisation/organizationalUnitApi/getAllOrganizationalUnits",
+ };
+ },
+}
\ No newline at end of file
diff --git a/public/js/api/factory/ort.js b/public/js/api/factory/ort.js
index 2e06d6b71..ee6a477ac 100644
--- a/public/js/api/factory/ort.js
+++ b/public/js/api/factory/ort.js
@@ -16,11 +16,25 @@
*/
export default {
- getContentID(ort_kurbz) {
+ getAllRooms(params) {
+ return {
+ method: 'get',
+ url: 'api/frontend/v1/Ort/getAllRooms',
+ params: {
+ "filter[organizationalUnitShortCode]" : params.organizationalUnitShortCode,
+ "filter[locationId]" : params.locationId,
+ "filter[buildingComponent]" : params.buildingComponent,
+ "filter[isForTrainingProgram]" : params.isForTrainingProgram,
+ "filter[isReservationNeeded]" : params.isReservationNeeded,
+ "filter[isActive]" : params.isActive,
+ }
+ }
+ },
+ getContentID(ort_kurzbz) {
return {
method: 'get',
url: '/api/frontend/v1/Ort/ContentID',
- params: { ort_kurzbz: ort_kurbz }
+ params: { ort_kurzbz: ort_kurzbz }
};
},
getRooms(datum, von, bis, typ, personenanzahl = 0) {
@@ -30,11 +44,37 @@ export default {
params: { datum, von, bis, typ, personenanzahl }
};
},
+ getRoom(ort_kurzbz) {
+ return {
+ method: 'get',
+ url: '/api/frontend/v1/Ort/getRoom/' + ort_kurzbz,
+ };
+ },
getRoomTypes() {
return {
method: 'get',
url: '/api/frontend/v1/Ort/getTypes',
params: { }
};
+ },
+ createRoom(roomData) {
+ return {
+ method: 'post',
+ url: '/api/frontend/v1/Ort/createRoom',
+ params: roomData
+ }
+ },
+ updateRoom(roomId, roomData) {
+ return {
+ method: 'post',
+ url: '/api/frontend/v1/Ort/updateRoom/' + roomId,
+ params: roomData
+ }
+ },
+ deleteRoom(ort_kurzbz) {
+ return {
+ method: 'post',
+ url: '/api/frontend/v1/Ort/deleteRoom/' + ort_kurzbz,
+ }
}
};
\ No newline at end of file
diff --git a/public/js/api/factory/roomManager.js b/public/js/api/factory/roomManager.js
new file mode 100644
index 000000000..c538e7596
--- /dev/null
+++ b/public/js/api/factory/roomManager.js
@@ -0,0 +1,18 @@
+
+export default {
+ getAllRooms(params) {
+ console.log("API Call with params: ", params);
+ return {
+ method: 'get',
+ url: 'api/frontend/v1/Ort/getAllRooms',
+ params: {
+ "filter[organizationalUnitShortCode]" : params.organizationalUnitShortCode,
+ "filter[locationId]" : params.locationId,
+ "filter[buildingComponent]" : params.buildingComponent,
+ "filter[isForTrainingProgram]" : params.isForTrainingProgram,
+ "filter[isReservationNeeded]" : params.isReservationNeeded,
+ "filter[isActive]" : params.isActive,
+ }
+ }
+ },
+};
\ No newline at end of file
diff --git a/public/js/apps/RoomManagerApp.js b/public/js/apps/RoomManagerApp.js
new file mode 100644
index 000000000..2e86e54e1
--- /dev/null
+++ b/public/js/apps/RoomManagerApp.js
@@ -0,0 +1,54 @@
+/**
+ * Copyright (C) 2023 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 .
+ */
+
+import RoomManagerOverview from "../components/RoomManager/RoomManagerOverview.js";
+
+import FhcAlert from "../plugins/FhcAlert.js";
+import Phrasen from "../plugins/Phrasen.js";
+import FhcApi from "../plugins/Api.js";
+
+import {capitalize} from "../helpers/StringHelpers.js";
+
+const ciPath =
+ FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, "") +
+ FHC_JS_DATA_STORAGE_OBJECT.ci_router;
+
+const router = VueRouter.createRouter({
+ history: VueRouter.createWebHistory(),
+ routes: [
+ {
+ name: "overview",
+ path: `/${ciPath}/RoomManager`,
+ component: RoomManagerOverview,
+ },
+ ],
+});
+
+const app = Vue.createApp({
+ components: {
+ RoomManagerOverview
+ },
+});
+
+app.config.globalProperties.$capitalize = capitalize;
+
+app.use(router)
+ .use(primevue.config.default, { zIndex: { overlay: 9999 } })
+ .use(FhcAlert)
+ .use(Phrasen)
+ .use(FhcApi)
+ .mount("#main");
diff --git a/public/js/components/RoomManager/RoomFormModal.js b/public/js/components/RoomManager/RoomFormModal.js
new file mode 100644
index 000000000..a8e83100c
--- /dev/null
+++ b/public/js/components/RoomManager/RoomFormModal.js
@@ -0,0 +1,436 @@
+import ApiRoom from "../../../js/api/factory/ort.js";
+import ApiLocation from "../../../js/api/factory/location.js";
+import ApiOrganizationalUnit from "../../../js/api/factory/organizationalUnit.js";
+
+import BsModal from "../Bootstrap/Modal.js";
+import CoreForm from "../Form/Form.js";
+import FormInput from "../Form/Input.js";
+
+export default {
+ name: "RoomFormModal",
+ components: {
+ BsModal,
+ CoreForm,
+ FormInput,
+ },
+ props: {
+ isVisible: {
+ type: Boolean,
+ required: true,
+ },
+ editedRoomShortCode: {
+ type: String,
+ default: null,
+ },
+ },
+ emits: ["hideBsModal", "roomCreated", "roomUpdated"],
+ watch: {
+ isVisible(newValue) {
+ if (newValue) {
+ this.$refs.roomFormModal.show();
+ } else {
+ this.$refs.roomFormModal.hide();
+ }
+ },
+ editedRoomShortCode(newValue) {
+ if (newValue) {
+ this.editRoom(newValue);
+ } else {
+ this.resetRoomForm();
+ }
+ },
+ },
+ data: () => {
+ return {
+ isEditInProgress: false,
+ organizationalUnits: [],
+ filteredOrganizationalUnits: [],
+ locations: [],
+ editedRoom: null,
+ roomFormData: {
+ aktiv: true,
+ },
+ };
+ },
+ computed: {
+ dropdownParsedOrganizationalUnits() {
+ return this.organizationalUnits.map((unit) => {
+ return {
+ label: `${unit.bezeichnung} (${unit.organisationseinheittyp_kurzbz})`,
+ value: unit.oe_kurzbz,
+ };
+ });
+ },
+ },
+ methods: {
+ filterOrganizationalUnits(event) {
+ let defaultItem = {
+ label: "----------",
+ value: null,
+ };
+
+ const query = event.query.toLowerCase();
+ if (!query) {
+ return (this.filteredOrganizationalUnits = [
+ defaultItem,
+ ...this.dropdownParsedOrganizationalUnits,
+ ]);
+ }
+
+ return (this.filteredOrganizationalUnits = [defaultItem].concat(
+ this.dropdownParsedOrganizationalUnits.filter((unit) => {
+ return unit.label.toLowerCase().includes(query);
+ }),
+ ));
+ },
+ createRoom() {
+ return this.$refs.roomForm
+ .call(ApiRoom.createRoom(this.getApiCallParsedRoomFormData()))
+ .then((response) => {
+ this.$fhcAlert.alertSuccess(this.$p.t("ui", "successSave"));
+ this.$emit("roomCreated");
+ this.resetRoomForm();
+ this.hideRoomFormModal();
+ });
+ },
+ async editRoom(roomShortCode) {
+ let getLocationsResponse = await this.$api.call(
+ ApiRoom.getRoom(roomShortCode),
+ );
+ if (getLocationsResponse.meta.status === "success") {
+ this.editedRoom = getLocationsResponse.data;
+ } else {
+ console.error(
+ "Error fetching room data:",
+ getLocationsResponse.meta.message,
+ );
+ this.$fhcAlert.alertError(this.$p.t("ui", "errorLoadingRoomData"));
+ return;
+ }
+
+
+ this.isEditInProgress = true;
+
+ let orgUnit = this.organizationalUnits.find(
+ (unit) => unit.oe_kurzbz === this.editedRoom.oe_kurzbz,
+ );
+
+ let orgUnitData = {
+ label: `${orgUnit.bezeichnung} (${orgUnit.organisationseinheittyp_kurzbz})`,
+ value: orgUnit.oe_kurzbz,
+ };
+
+ this.roomFormData = {
+ locationId: this.editedRoom.standort_id,
+ organizationalUnit: orgUnitData,
+ contentId: this.editedRoom.content_id,
+ kurzbezeichnung: this.editedRoom.ort_kurzbz,
+ bezeichnung: this.editedRoom.bezeichnung,
+ planbezeichnung: this.editedRoom.planbezeichnung,
+ aktiv: this.editedRoom.aktiv,
+ lehre: this.editedRoom.lehre,
+ reservieren: this.editedRoom.reservieren,
+ maxPerson: this.editedRoom.max_person,
+ stockwerk: this.editedRoom.stockwerk,
+ lageplan: this.editedRoom.lageplan,
+ dislozierung: this.editedRoom.dislozierung,
+ kosten: this.editedRoom.kosten,
+ ausstattung: this.editedRoom.ausstattung,
+ telefonklappe: this.editedRoom.telefonklappe,
+ quadratmeter: this.editedRoom.m2,
+ gebaudeteil: this.editedRoom.gebteil,
+ arbeitsplatze: this.editedRoom.arbeitsplaetze,
+ };
+
+ this.$refs.roomFormModal.show();
+ },
+ updateRoom() {
+ return this.$refs.roomForm
+ .call(
+ ApiRoom.updateRoom(
+ this.editedRoom.ort_kurzbz,
+ this.getApiCallParsedRoomFormData(),
+ ),
+ )
+ .then((response) => {
+ this.$fhcAlert.alertSuccess(this.$p.t("ui", "successSave"));
+ this.$emit("roomUpdated");
+ this.resetRoomForm();
+ this.hideRoomFormModal();
+ });
+ },
+ getApiCallParsedRoomFormData() {
+ return {
+ standort_id: this.roomFormData.locationId,
+ oe_kurzbz: this.roomFormData.organizationalUnit?.value,
+ content_id: this.roomFormData.contentId,
+ 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,
+ lageplan: this.roomFormData.lageplan,
+ dislozierung: this.roomFormData.dislozierung,
+ kosten: this.roomFormData.kosten,
+ ausstattung: this.roomFormData.ausstattung,
+ telefonklappe: this.roomFormData.telefonklappe,
+ m2: this.roomFormData.quadratmeter,
+ gebteil: this.roomFormData.gebaudeteil,
+ arbeitsplatze: this.roomFormData.arbeitsplatze,
+ };
+ },
+ hideRoomFormModal() {
+ this.$refs.roomFormModal.hide();
+ this.$emit("hideBsModal");
+ this.resetRoomForm();
+ },
+ resetRoomForm() {
+ this.isEditInProgress = false;
+ this.editedRoom = null;
+ this.roomFormData = {
+ aktiv: true,
+ };
+ },
+ },
+ async created() {
+ let getLocationsResponse = await this.$api.call(
+ ApiLocation.getLocationsByCompanyType("Intern"),
+ );
+ if (getLocationsResponse.meta.status === "success") {
+ this.locations = getLocationsResponse.data;
+ } else {
+ console.error(
+ "Error fetching locations:",
+ getLocationsResponse.meta.message,
+ );
+ }
+
+ let getAllOrganizationalUnitsResponse = await this.$api.call(
+ ApiOrganizationalUnit.getAllOrganizationalUnits(),
+ );
+ if (getAllOrganizationalUnitsResponse.meta.status === "success") {
+ this.organizationalUnits = getAllOrganizationalUnitsResponse.data.sort(
+ (a, b) => a.bezeichnung.localeCompare(b.bezeichnung),
+ );
+ } else {
+ console.error(
+ "Error fetching organizational units:",
+ getAllOrganizationalUnitsResponse.meta.message,
+ );
+ }
+ },
+ template: /* html */ `
+ { $emit('hideBsModal'); resetRoomForm(); }" class="modal-lg">
+
+ {{$capitalize($p.t('ui', 'createRoomModalTitle'))}}
+ {{$capitalize($p.t('ui', 'editRoomModalTitle'))}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+};
diff --git a/public/js/components/RoomManager/RoomManagerOverview.js b/public/js/components/RoomManager/RoomManagerOverview.js
new file mode 100644
index 000000000..56623008e
--- /dev/null
+++ b/public/js/components/RoomManager/RoomManagerOverview.js
@@ -0,0 +1,390 @@
+import ApiRoom from "../../../js/api/factory/ort.js";
+import ApiLocation from "../../../js/api/factory/location.js";
+import ApiOrganizationalUnit from "../../../js/api/factory/organizationalUnit.js";
+
+import { CoreFilterCmpt } from "../filter/Filter.js";
+import CoreForm from "../Form/Form.js";
+import FormInput from "../Form/Input.js";
+import RoomFormModal from "./RoomFormModal.js";
+
+import ApiCms from "../../../js/api/factory/cms.js";
+
+export default {
+ name: "RoomManagerOverview",
+ components: {
+ CoreFilterCmpt,
+ CoreForm,
+ FormInput,
+ RoomFormModal,
+ },
+ watch: {
+ filterData: {
+ handler(newValue) {
+ this.$refs.roomManagerOverviewTable.tabulator.setData("/", {
+ organizationalUnitShortCode: newValue.organizationalUnit?.value,
+ locationId: newValue.locationId,
+ buildingComponent: newValue.buildingComponent,
+ isForTrainingProgram: newValue.isForTrainingProgram,
+ isReservationNeeded: newValue.isReservationNeeded,
+ isActive: newValue.isActive,
+ });
+ },
+ deep: true,
+ },
+ },
+ data() {
+ return {
+ phrasesLoaded: false,
+ filterData: {
+ locationId: null,
+ organizationalUnit: null,
+ buildingComponent: null,
+ isForTrainingProgram: false,
+ isReservationNeeded: false,
+ isActive: false,
+ },
+ locations: [],
+ organizationalUnits: [],
+ filteredOrganizationalUnits: [],
+ buildingComponents: ["A", "B", "C", "D", "E", "F"],
+ isRoomFormModalVisible: false,
+ editedRoomShortCode: null,
+ };
+ },
+ computed: {
+ tabulatorOptions() {
+ const options = {
+ ajaxURL: "dummy",
+ ajaxRequestFunc: async () =>
+ this.$api.call(
+ ApiRoom.getAllRooms({
+ organizationalUnitShortCode:
+ this.filterData.organizationalUnit?.value,
+ locationId: this.filterData.locationId,
+ buildingComponent: this.filterData.buildingComponent,
+ isForTrainingProgram: this.filterData.isForTrainingProgram,
+ isReservationNeeded: this.filterData.isReservationNeeded,
+ isActive: this.filterData.isActive,
+ }),
+ ),
+ ajaxResponse: (url, params, response) => response.data,
+ persistenceID: "core_class_schedule_validity_periods",
+ selectableRows: true,
+ columns: [
+ {
+ title: this.$capitalize(this.$p.t("gruppenmanagement", "kurzbezeichnung")),
+ field: "ort_kurzbz",
+ },
+ {
+ title: this.$capitalize(this.$p.t("gruppenmanagement", "bezeichnung")),
+ field: "bezeichnun",
+ },
+ {
+ title: this.$capitalize(this.$p.t("ui", "planbezeichnung")),
+ field: "planbezeichnung",
+ },
+ {
+ title: this.$capitalize(this.$p.t("ui", "maxPersons")),
+ field: "max_person",
+ },
+ {
+ title: this.$capitalize(this.$p.t("ui", "arbeitsplaetze")),
+ field: "arbeitsplaetze",
+ },
+ {
+ title: this.$capitalize(this.$p.t("ui", "quadratmeter")),
+ field: "m2",
+ },
+ {
+ title: this.$capitalize(this.$p.t("lehre", "organisationseinheit")),
+ field: "oe_kurzbz",
+ },
+ {
+ title: this.$capitalize(this.$p.t("ui", "lehre")),
+ field: "lehre",
+ },
+ {
+ title: this.$capitalize(this.$p.t("ui", "reservieren")),
+ field: "reservieren",
+ },
+ {
+ title: this.$capitalize(this.$p.t("gruppenmanagement", "aktiv")),
+ field: "aktiv",
+ },
+ {
+ title: this.$capitalize(this.$p.t("ui", "kosten")),
+ field: "kosten",
+ },
+ {
+ title: this.$capitalize(this.$p.t("ui", "stockwerk")),
+ field: "stockwerk",
+ },
+ {
+ title: this.$capitalize(this.$p.t("global", "actions")),
+ field: "actions",
+ minWidth: 150,
+ maxWidth: 150,
+ formatter: (cell, formatterParams, onRendered) => {
+ let container = document.createElement("div");
+ container.className = "d-flex gap-2";
+
+ let button = document.createElement("button");
+
+ button = document.createElement("button");
+ button.className = "btn btn-outline-secondary btn-action";
+ button.innerHTML = '';
+ button.title = this.$p.t(
+ "ui",
+ "btn_editRoom",
+ );
+ button.addEventListener("click", (event) =>
+ this.editRoom(
+ cell.getData().ort_kurzbz,
+ ),
+ );
+ container.append(button);
+
+ button = document.createElement("button");
+ button.className =
+ "btn btn-outline-secondary btn-action bg-danger";
+ button.innerHTML = '';
+ button.title = this.$p.t(
+ "ui",
+ "btn_deleteRoom",
+ );
+ button.addEventListener("click", () => {
+ let isDeletionConfirmed = confirm(
+ this.$p.t(
+ "ui",
+ "deleteRoomConfirmation",
+ ),
+ );
+ if (!isDeletionConfirmed) return;
+
+ this.deleteRoom(
+ cell.getData().ort_kurzbz
+ );
+ });
+ container.append(button);
+
+ return container;
+ },
+ frozen: true,
+ },
+ ],
+ };
+ return options;
+ },
+ tabulatorEvents() {
+ const events = [
+ {
+ event: "renderComplete",
+ handler: async () => {},
+ },
+ ];
+ return events;
+ },
+ dropdownParsedOrganizationalUnits() {
+ return this.organizationalUnits.map((unit) => {
+ return {
+ label: `${unit.bezeichnung} (${unit.organisationseinheittyp_kurzbz})`,
+ value: unit.oe_kurzbz,
+ };
+ });
+ },
+ },
+ methods: {
+ filterOrganizationalUnits(event) {
+ let defaultItem = {
+ label: "----------",
+ value: null,
+ };
+
+ const query = event.query.toLowerCase();
+ if (!query) {
+ return (this.filteredOrganizationalUnits = [
+ defaultItem,
+ ...this.dropdownParsedOrganizationalUnits,
+ ]);
+ }
+
+ return (this.filteredOrganizationalUnits = [defaultItem].concat(
+ this.dropdownParsedOrganizationalUnits.filter((unit) => {
+ return unit.label.toLowerCase().includes(query);
+ }),
+ ));
+ },
+ showRoomFormModal() {
+ this.isRoomFormModalVisible = true;
+ },
+ editRoom(roomShortCode) {
+ this.editedRoomShortCode = roomShortCode;
+ },
+ deleteRoom(roomShortCode) {
+ this.$api
+ .call(ApiRoom.deleteRoom(roomShortCode))
+ .then((response) => {
+ if (response.meta.status === "success") {
+ this.$refs.roomManagerOverviewTable.reloadTable();
+ alert(this.$p.t("ui", "roomDeletedSuccessfully"));
+ } else {
+ console.error("Error deleting room:", response.meta.message);
+ alert(this.$p.t("ui", "errorDeletingRoom"));
+ }
+ })
+ .catch((error) => {
+ console.error("Error deleting room:", error);
+ alert(this.$p.t("ui", "errorDeletingRoom"));
+ });
+ }
+ },
+ async created() {
+ let getContent = await this.$api.call(ApiCms.content(7601));
+ if (getContent.meta.status === "success") {
+ console.log;
+ } else {
+ console.error("Error fetching locations:", getContent.meta.message);
+ }
+
+ let getLocationsResponse = await this.$api.call(
+ ApiLocation.getLocationsByCompanyType("Intern"),
+ );
+ if (getLocationsResponse.meta.status === "success") {
+ this.locations = getLocationsResponse.data;
+ } else {
+ console.error(
+ "Error fetching locations:",
+ getLocationsResponse.meta.message,
+ );
+ }
+
+ let getAllOrganizationalUnitsResponse = await this.$api.call(
+ ApiOrganizationalUnit.getAllOrganizationalUnits(),
+ );
+ if (getAllOrganizationalUnitsResponse.meta.status === "success") {
+ this.organizationalUnits = getAllOrganizationalUnitsResponse.data.sort(
+ (a, b) => a.bezeichnung.localeCompare(b.bezeichnung),
+ );
+ } else {
+ console.error(
+ "Error fetching organizational units:",
+ getAllOrganizationalUnitsResponse.meta.message,
+ );
+ }
+ },
+ mounted() {
+ this.$p
+ .loadCategory(["global", "lehre", "ui", "gruppenmanagement", "core", "person"])
+ .then(() => {
+ this.phrasesLoaded = true;
+ });
+ },
+ template: /* html */ `
+
+
{{ $capitalize($p.t("ui", "roomManagerOverviewHeading")) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{ isRoomFormModalVisible = false; editedRoomShortCode = null; }"
+ @roomCreated="() => { $refs.roomManagerOverviewTable.reloadTable(); editedRoomShortCode = null; }"
+ @roomUpdated="() => { $refs.roomManagerOverviewTable.reloadTable(); editedRoomShortCode = null; }"
+ />
+
+ `,
+};
diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php
index 0476db2c9..e42befef2 100644
--- a/system/phrasesupdate.php
+++ b/system/phrasesupdate.php
@@ -58177,6 +58177,486 @@ I have been informed that I am under no obligation to consent to the transmissio
)
),
// ### Phrases Dashboard Admin END
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'roomManagerOverviewHeading',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'raumverwaltung übersicht',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'room management overview',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'addRoomButton',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'raum hinzufügen',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'add room',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'planbezeichnung',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'planbezeichnung',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'plan name',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'maxPersons',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'max. personen',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'max. persons',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'arbeitsplaetze',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'arbeitsplätze',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'workplaces',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'quadratmeter',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'quadratmeter',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'square meters',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'reservieren',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'reservieren',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'reserve',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'kosten',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'kosten',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'costs',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'stockwerk',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'stockwerk',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'floor',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'btn_editRoom',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'raum bearbeiten',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'edit room',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'btn_deleteRoom',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'raum löschen',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'delete room',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'deleteRoomConfirmation',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Sind Sie sicher, dass Sie diesen Raum löschen möchten?',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Are you sure you want to delete this room?',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'roomDeletedSuccessfully',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Raum erfolgreich gelöscht',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Room deleted successfully',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'errorDeletingRoom',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Fehler beim Löschen des Raums',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Error deleting room',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'buildingComponent',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'gebäudekomponente',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'building component',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'lehre',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'lehre',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'teaching',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'errorLoadingRoomData',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Fehler beim Laden der Raumdaten',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Error loading room data',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'createRoomModalTitle',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'raum erstellen',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'create room',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'editRoomModalTitle',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'raum bearbeiten',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'edit room',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'gebaudeteil',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'gebäudeteil',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'building component',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'contentId',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'inhalt ID',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'content ID',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'dislozierung',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'dislozierung',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'relocation',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'lageplan',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'lageplan',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'site plan',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'ausstattung',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'ausstattung',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'equipment',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
);