diff --git a/application/controllers/api/frontend/v1/ClassScheduleApi.php b/application/controllers/api/frontend/v1/ClassScheduleApi.php index 6c4bac78b..2402cb5fc 100644 --- a/application/controllers/api/frontend/v1/ClassScheduleApi.php +++ b/application/controllers/api/frontend/v1/ClassScheduleApi.php @@ -61,6 +61,13 @@ class ClassScheduleApi extends FHCAPI_Controller public function getAllClassTimeValidityPeriods() { + $entitledOrganizationalUnitsShortCodes = $this->permissionlib->getOE_isEntitledFor('lehre/unterrichtszeiten_gk'); + + $organizationalUnitShortCode = $this->input->get('organizationalUnitShortCode'); + $validityPeriodFrom = $this->input->get('validityPeriodFrom'); + $validityPeriodTo = $this->input->get('validityPeriodTo'); + + $this->ClassTimeSlotValidityPeriodModel->db->where_in('lehre.tbl_unterrichtszeiten_gueltigkeit.oe_kurzbz', $entitledOrganizationalUnitsShortCodes); $this->ClassTimeSlotValidityPeriodModel->addSelect( 'lehre.tbl_unterrichtszeiten_gueltigkeit.*,' . 'public.tbl_organisationseinheit.bezeichnung as organisationseinheit_bezeichnung,' . @@ -72,6 +79,20 @@ class ClassScheduleApi extends FHCAPI_Controller $this->ClassTimeSlotValidityPeriodModel->addJoin('public.tbl_organisationseinheit', 'public.tbl_organisationseinheit.oe_kurzbz=lehre.tbl_unterrichtszeiten_gueltigkeit.oe_kurzbz', 'LEFT'); $this->ClassTimeSlotValidityPeriodModel->addJoin('lehre.tbl_unterrichtszeiten_typ', 'lehre.tbl_unterrichtszeiten_typ.unterrichtszeitentyp_kurzbz=lehre.tbl_unterrichtszeiten_gueltigkeit.unterrichtszeitentyp_kurzbz', 'LEFT'); $this->ClassTimeSlotValidityPeriodModel->addOrder('gueltig_von', 'DESC'); + + if ($organizationalUnitShortCode) { + $this->ClassTimeSlotValidityPeriodModel->db->where('lehre.tbl_unterrichtszeiten_gueltigkeit.oe_kurzbz', $organizationalUnitShortCode); + } + + if ($validityPeriodFrom) { + $this->ClassTimeSlotValidityPeriodModel->db + ->where('lehre.tbl_unterrichtszeiten_gueltigkeit.gueltig_von >=', date('Y-m-d', strtotime($validityPeriodFrom))); + } + if ($validityPeriodTo) { + $this->ClassTimeSlotValidityPeriodModel->db + ->where('lehre.tbl_unterrichtszeiten_gueltigkeit.gueltig_bis <=', date('Y-m-d', strtotime($validityPeriodTo))); + } + $class_time_slot_validity_period_res = $this->ClassTimeSlotValidityPeriodModel->load(); $class_time_slot_validity_period_res = $this->getDataOrTerminateWithError($class_time_slot_validity_period_res); $this->terminateWithSuccess($class_time_slot_validity_period_res); @@ -79,6 +100,10 @@ class ClassScheduleApi extends FHCAPI_Controller public function getAllClassTimeValidityPeriodsPerOrganizationalUnit($organizationUnitId) { + if (!$this->isUserEntitledForOrganizationalUnit($organizationUnitId, 'lehre/unterrichtszeiten_gk')) { + $this->terminateWithError($this->p->t('ui', 'keineBerechtigung')); + } + $this->ClassTimeSlotValidityPeriodModel->addSelect( 'lehre.tbl_unterrichtszeiten_gueltigkeit.*,' . 'public.tbl_organisationseinheit.bezeichnung as organisationseinheit_bezeichnung,' . @@ -97,11 +122,24 @@ class ClassScheduleApi extends FHCAPI_Controller public function getClassTimeValidityPeriod($classTimeSlotValidityPeriodId) { - $this->ClassTimeSlotValidityPeriodModel->addSelect('lehre.tbl_unterrichtszeiten_gueltigkeit.*, public.tbl_organisationseinheit.oe_kurzbz as oe_kurzbz, lehre.tbl_studienplan.studienplan_id, lehre.tbl_studienplan.bezeichnung as studienplan_bezeichnung'); + $this->ClassTimeSlotValidityPeriodModel->addSelect(' + lehre.tbl_unterrichtszeiten_gueltigkeit.*, + public.tbl_organisationseinheit.oe_kurzbz as oe_kurzbz, + public.tbl_organisationseinheit.bezeichnung as oe_bezeichnung, + public.tbl_organisationseinheit.organisationseinheittyp_kurzbz as oe_organisationseinheittyp_kurzbz, + lehre.tbl_studienplan.studienplan_id, + lehre.tbl_studienplan.bezeichnung as studienplan_bezeichnung, + '); $this->ClassTimeSlotValidityPeriodModel->addJoin('public.tbl_organisationseinheit', 'public.tbl_organisationseinheit.oe_kurzbz=lehre.tbl_unterrichtszeiten_gueltigkeit.oe_kurzbz', 'LEFT'); $this->ClassTimeSlotValidityPeriodModel->addJoin('lehre.tbl_studienplan', 'lehre.tbl_studienplan.studienplan_id=lehre.tbl_unterrichtszeiten_gueltigkeit.studienplan_id', 'LEFT'); $class_time_slot_validity_period_res = $this->ClassTimeSlotValidityPeriodModel->load($classTimeSlotValidityPeriodId); + $class_time_slot_validity_period_res = $this->getDataOrTerminateWithError($class_time_slot_validity_period_res); + + if (!$this->isUserEntitledForOrganizationalUnit($class_time_slot_validity_period_res[0]->oe_kurzbz, 'lehre/unterrichtszeiten_gk')) { + $this->terminateWithError($this->p->t('ui', 'keineBerechtigung')); + } + $this->terminateWithSuccess($class_time_slot_validity_period_res); } @@ -126,6 +164,10 @@ class ClassScheduleApi extends FHCAPI_Controller if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array()); + if (!$this->isUserEntitledForOrganizationalUnit($this->input->post('organizationalUnitShortCode'), 'lehre/unterrichtszeiten_gk')) { + $this->terminateWithError($this->p->t('ui', 'keineBerechtigung')); + } + $this->db->trans_start(); $result = $this->ClassTimeSlotValidityPeriodModel->insert([ @@ -170,6 +212,10 @@ class ClassScheduleApi extends FHCAPI_Controller if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array()); + if (!$this->isUserEntitledForOrganizationalUnit($this->input->post('organizationalUnitShortCode'), 'lehre/unterrichtszeiten_gk')) { + $this->terminateWithError($this->p->t('ui', 'keineBerechtigung')); + } + $this->db->trans_start(); $result = $this->ClassTimeSlotValidityPeriodModel->update($classTimeSlotValidityPeriodId, [ @@ -193,6 +239,12 @@ class ClassScheduleApi extends FHCAPI_Controller public function deleteClassTimeSlotValidityPeriod($classTimeSlotValidityPeriodId) { + $validityPeriodResult = $this->ClassTimeSlotValidityPeriodModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]); + $validityPeriodResult = $this->getDataOrTerminateWithError($validityPeriodResult)[0]; + if (!$this->isUserEntitledForOrganizationalUnit($validityPeriodResult->oe_kurzbz, 'lehre/unterrichtszeiten_gk')) { + $this->terminateWithError($this->p->t('ui', 'keineBerechtigung')); + } + $this->db->trans_start(); $result = $this->ClassTimeSlotModel->delete(['unterrichtszeitengueltigkeit_id'=> $classTimeSlotValidityPeriodId]); @@ -212,6 +264,12 @@ class ClassScheduleApi extends FHCAPI_Controller public function getClassTimeSlotsForValidityPeriod($classTimeSlotValidityPeriodId) { + $validityPeriodResult = $this->ClassTimeSlotValidityPeriodModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]); + $validityPeriodResult = $this->getDataOrTerminateWithError($validityPeriodResult)[0]; + if (!$this->isUserEntitledForOrganizationalUnit($validityPeriodResult->oe_kurzbz, 'lehre/unterrichtszeiten_gk')) { + $this->terminateWithError($this->p->t('ui', 'keineBerechtigung')); + } + $this->ClassTimeSlotModel->addOrder('insertamum', 'DESC'); $class_time_slots_res = $this->ClassTimeSlotModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]); $class_time_slots_res = $this->getDataOrTerminateWithError($class_time_slots_res); @@ -223,6 +281,12 @@ class ClassScheduleApi extends FHCAPI_Controller $this->form_validation->set_rules('unterrichtszeiten', 'Class Time Slots', 'callback_validate_items_in_class_time_slots'); if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array()); + $validityPeriodResult = $this->ClassTimeSlotValidityPeriodModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]); + $validityPeriodResult = $this->getDataOrTerminateWithError($validityPeriodResult)[0]; + if (!$this->isUserEntitledForOrganizationalUnit($validityPeriodResult->oe_kurzbz, 'lehre/unterrichtszeiten_gk')) { + $this->terminateWithError($this->p->t('ui', 'keineBerechtigung')); + } + $this->db->trans_start(); $timeSlotGroupIdentifier = uniqid(); @@ -253,6 +317,12 @@ class ClassScheduleApi extends FHCAPI_Controller $this->form_validation->set_rules('unterrichtszeiten', 'Class Time Slots', 'callback_validate_items_in_class_time_slots'); if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array()); + $validityPeriodResult = $this->ClassTimeSlotValidityPeriodModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]); + $validityPeriodResult = $this->getDataOrTerminateWithError($validityPeriodResult)[0]; + if (!$this->isUserEntitledForOrganizationalUnit($validityPeriodResult->oe_kurzbz, 'lehre/unterrichtszeiten_gk')) { + $this->terminateWithError($this->p->t('ui', 'keineBerechtigung')); + } + $this->db->trans_start(); $timeSlotGroupIdentifier = uniqid(); @@ -286,6 +356,12 @@ class ClassScheduleApi extends FHCAPI_Controller } public function deleteClassTimeSlotsForValidityPeriodPerGroup($classTimeSlotValidityPeriodId, $groupIdentifikator) { + $validityPeriodResult = $this->ClassTimeSlotValidityPeriodModel->loadWhere(['unterrichtszeitengueltigkeit_id' => $classTimeSlotValidityPeriodId]); + $validityPeriodResult = $this->getDataOrTerminateWithError($validityPeriodResult)[0]; + if (!$this->isUserEntitledForOrganizationalUnit($validityPeriodResult->oe_kurzbz, 'lehre/unterrichtszeiten_gk')) { + $this->terminateWithError($this->p->t('ui', 'keineBerechtigung')); + } + $this->db->trans_start(); $result = $this->ClassTimeSlotModel->delete(['unterrichtszeitengueltigkeit_id'=> $classTimeSlotValidityPeriodId, 'unterrichtszeit_gruppe_identifikator' => $groupIdentifikator]); @@ -542,5 +618,11 @@ class ClassScheduleApi extends FHCAPI_Controller return true; } + + private function isUserEntitledForOrganizationalUnit($organizationalUnitShortCode, $requiredPermission) + { + $entitledOrganizationalUnitsShortCodes = $this->permissionlib->getOE_isEntitledFor($requiredPermission); + return in_array($organizationalUnitShortCode, $entitledOrganizationalUnitsShortCodes); + } } diff --git a/application/controllers/api/frontend/v1/organisation/OrganizationalUnitApi.php b/application/controllers/api/frontend/v1/organisation/OrganizationalUnitApi.php index 6fa5a50f8..f79b67b51 100644 --- a/application/controllers/api/frontend/v1/organisation/OrganizationalUnitApi.php +++ b/application/controllers/api/frontend/v1/organisation/OrganizationalUnitApi.php @@ -30,7 +30,7 @@ class OrganizationalUnitApi extends FHCAPI_Controller $this->load->library('form_validation'); - $this->load->model('education/ClassTimeSlotValidityPeriod_model', "ClassTimeSlotValidityPeriodModel"); + $this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); // Loads phrases system $this->loadPhrases([ @@ -44,8 +44,11 @@ class OrganizationalUnitApi extends FHCAPI_Controller public function getAllOrganizationalUnits() { - $this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); + $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); diff --git a/application/controllers/api/frontend/v1/organisation/Studienplan.php b/application/controllers/api/frontend/v1/organisation/Studienplan.php index 94d195f90..f22e6eb9f 100644 --- a/application/controllers/api/frontend/v1/organisation/Studienplan.php +++ b/application/controllers/api/frontend/v1/organisation/Studienplan.php @@ -22,7 +22,8 @@ class Studienplan extends FHCAPI_Controller parent::__construct([ 'getAllStudyPlans' => self::PERM_LOGGED, 'getStudyPlansByOrganizationalUnitAndSemesterDates' => self::PERM_LOGGED, - 'getBySemester' => self::PERM_LOGGED + 'getBySemester' => self::PERM_LOGGED, + 'getStudyPlan' => self::PERM_LOGGED, ]); } @@ -96,4 +97,15 @@ class Studienplan extends FHCAPI_Controller $this->terminateWithSuccess(hasData($result) ? getData($result) : []); } + + public function getStudyPlan($id) + { + $this->load->model('organisation/Studienplan_model', 'StudienplanModel'); + + $result = $this->StudienplanModel->loadWhere(['studienplan_id' => $id]); + if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_DB); + if (!hasData($result)) return $this->terminateWithSuccess(null); + + $this->terminateWithSuccess(getData($result)[0]); + } } diff --git a/application/views/lehre/class_schedule/index.php b/application/views/lehre/class_schedule/index.php index 7d00e8c9c..b27a97457 100644 --- a/application/views/lehre/class_schedule/index.php +++ b/application/views/lehre/class_schedule/index.php @@ -21,7 +21,8 @@ $includesArray = array( 'public/css/components/verticalsplit.css', 'public/extensions/FHC-Core-Developer/css/FhcMain.css', 'public/css/components/calendar.css', - 'public/css/components/classSchedule.css' + 'public/css/components/classSchedule.css', + 'public/css/components/vue-datepicker.css', ) ); diff --git a/public/js/api/factory/classSchedule.js b/public/js/api/factory/classSchedule.js index cd4ce6bbb..a0a037f80 100644 --- a/public/js/api/factory/classSchedule.js +++ b/public/js/api/factory/classSchedule.js @@ -16,10 +16,11 @@ */ export default { - getAllClassTimeValidityPeriods() { + getAllClassTimeValidityPeriods(params) { return { method: "get", url: "/api/frontend/v1/ClassScheduleApi/getAllClassTimeValidityPeriods", + params, }; }, getAllClassTimeValidityPeriodsPerOrganizationalUnit(organizationUnitId) { diff --git a/public/js/api/factory/studienplan.js b/public/js/api/factory/studienplan.js index 133a8123d..42c7a9471 100644 --- a/public/js/api/factory/studienplan.js +++ b/public/js/api/factory/studienplan.js @@ -28,4 +28,10 @@ export default { }, }; }, + getStudyPlan(studienplan_id) { + return { + method: "get", + url: `api/frontend/v1/organisation/studienplan/getStudyPlan/${studienplan_id}`, + }; + }, }; diff --git a/public/js/apps/lehre/ClassScheduleApp.js b/public/js/apps/lehre/ClassScheduleApp.js index 0dc8e403f..abaf60dae 100644 --- a/public/js/apps/lehre/ClassScheduleApp.js +++ b/public/js/apps/lehre/ClassScheduleApp.js @@ -23,6 +23,8 @@ 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; @@ -64,6 +66,8 @@ const app = Vue.createApp({ }, }); +app.config.globalProperties.$capitalize = capitalize; + app .use(router) .use(primevue.config.default, { zIndex: { overlay: 9999 } }) diff --git a/public/js/components/ClassSchedule/ClassScheduleCalendarSelector.js b/public/js/components/ClassSchedule/ClassScheduleCalendarSelector.js index b436bae49..f9cdb8e72 100644 --- a/public/js/components/ClassSchedule/ClassScheduleCalendarSelector.js +++ b/public/js/components/ClassSchedule/ClassScheduleCalendarSelector.js @@ -115,6 +115,17 @@ export default { deep: true, immediate: true, }, + classTimeSlotTypes() { + this.overlays = this.overlays.map((overlay) => { + let type = this.classTimeSlotTypes.find( + (type) => type.unterrichtszeitentyp_kurzbz === overlay.type + ); + if (type) { + overlay.hexColor = type.hintergrundfarbe; + } + return overlay; + }); + }, overlays: { handler(newVal) { this.$emit("overlaysChanged", newVal); @@ -202,9 +213,14 @@ export default { return firstTimeSlotFragment + "-" + lastTimeSlotFragment; }, + userLanguage() { + return Vue.ref(FHC_JS_DATA_STORAGE_OBJECT.user_language); + } }, methods: { createOverlay() { + this.hideOverlayClassTimeTypePopover(); + let overlayElement; overlayElement = this.$refs.calendarSelectorContainer.querySelector( @@ -350,6 +366,8 @@ export default { this.$refs.calendarSelectorContainer .querySelector(`#${overlayId}`) .remove(); + + this.hideOverlayClassTimeTypePopover(); }, getLineNumberFromSelectedElementNumber(selectedElementNumber) { let timeSlotsCount = this.timeSlotsInDay.length; @@ -696,6 +714,7 @@ export default { this.selected = []; }, handleOverlayDrop(event) { + this.hideOverlayClassTimeTypePopover(); if (this.$props.isPreviewMode) return; let dropzoneItem = event.target; @@ -725,25 +744,22 @@ export default { `[data-number='${startElementNumber}']`, ); - // get mouse position const mouseY = event.clientY; - // get delta Y from mouse position to top of the dropzone item + const dropzoneItemRect = dropzoneItem.getBoundingClientRect(); const deltaY = mouseY - dropzoneItemRect.top; - // get top of the start element const startElementRect = startElement.getBoundingClientRect(); const startElementTop = startElementRect.top; - // add delta Y to top of the start element to get new top for the dropzone item const newTop = startElementTop + deltaY; - //find which item has the closest top to the new top and get its data-number attribute + const partBodies = this.$refs.calendarSelectorContainer.querySelectorAll( "div[data-weekday='" + dropzoneOverlay.weekday + "']", ); - // see which item has the new top in between its top and bottom and get its data-number attribute + let closestPartBody = null; partBodies.forEach((partBody) => { const rect = partBody.getBoundingClientRect(); @@ -1439,10 +1455,20 @@ export default { }); }, 10); }, + hideOverlayClassTimeTypePopover() { + if (this.visiblePopover) { + this.visiblePopover.dispose(); + this.visiblePopover = null; + } + }, + getClassTimeSlotTypeLabel(classTimeSlotType) { + if (!classTimeSlotType) return ""; + return this.userLanguage?.value === 'English' ? + classTimeSlotType.bezeichnung_mehrsprachig[1].value : classTimeSlotType.bezeichnung_mehrsprachig[0].value; + } }, unmounted() { - this.visiblePopover?.dispose(); - this.visiblePopover = null; + this.hideOverlayClassTimeTypePopover(); }, template: /*html*/ `
{{ $p.t("lehre", "ausbildungssemester") }}: {{ classTimeSlotValidityPeriod?.ausbildungssemester }}
- +{{ $p.t("ui", "noClassScheduleValidityPeriodTimeSlotsFound") }}
+{{ $p.t("ui", "noClassScheduleValidityPeriodTimeSlotsFound") }}
{{ $p.t("ui", "noClassScheduleValidityPeriodTimeSlotsFound") }}
+{{ $p.t("ui", "noClassScheduleValidityPeriodTimeSlotsFound") }}