diff --git a/application/controllers/api/frontend/v1/tempus/Coursepicker.php b/application/controllers/api/frontend/v1/tempus/Coursepicker.php index 686b39023..dc6def005 100644 --- a/application/controllers/api/frontend/v1/tempus/Coursepicker.php +++ b/application/controllers/api/frontend/v1/tempus/Coursepicker.php @@ -5,11 +5,13 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); class Coursepicker extends FHCAPI_Controller { private $_ci; + + const ALLOWED_COURSE_FILTER = ['uid', 'stg']; + public function __construct() { parent::__construct([ - 'search' => self::PERM_LOGGED, - 'getByStg' => self::PERM_LOGGED + 'getCourses' => self::PERM_LOGGED, ]); $this->_ci = &get_instance(); @@ -22,88 +24,40 @@ class Coursepicker extends FHCAPI_Controller $this->loadPhrases(['ui']); } - public function search() - { - $query = $this->input->get('query'); - if (is_null($query)) - $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); - - $query_words = explode(' ', $query); - - //TODO Where weiter anpassen z.B. Fachbereich - $this->_ci->LehreinheitModel->addSelect('tbl_lehreinheit.lehreinheit_id, - tbl_lehreinheit.lvnr, - tbl_lehreinheit.lehrfach_id, - lehrfach.kurzbz AS lehrfach, - lehrfach.bezeichnung AS lehrfach_bez, - lehrfach.farbe AS lehrfach_farbe, - tbl_lehreinheit.lehrform_kurzbz AS lehrform, - lema.mitarbeiter_uid AS lektor_uid, - tbl_mitarbeiter.kurzbz AS lektor, - tbl_studiengang.studiengang_kz, - upper(tbl_studiengang.typ::character varying::text || tbl_studiengang.kurzbz::text) AS studiengang, - lvb.semester, - lvb.verband, - lvb.gruppe, - lvb.gruppe_kurzbz, - tbl_lehreinheit.raumtyp, - tbl_lehreinheit.raumtypalternativ, - tbl_lehreinheit.stundenblockung, - tbl_lehreinheit.wochenrythmus, - lema.semesterstunden, - lema.planstunden, - tbl_lehreinheit.start_kw, - tbl_lehreinheit.anmerkung, - tbl_lehreinheit.studiensemester_kurzbz'); - - $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehreinheitmitarbeiter lema', 'tbl_lehreinheit.lehreinheit_id = lema.lehreinheit_id'); - $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehreinheitgruppe lvb', 'tbl_lehreinheit.lehreinheit_id = lvb.lehreinheit_id'); - $this->_ci->LehreinheitModel->addJoin('public.tbl_studiengang', 'lvb.studiengang_kz = tbl_studiengang.studiengang_kz'); - $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrveranstaltung lehrfach', 'tbl_lehreinheit.lehrfach_id = lehrfach.lehrveranstaltung_id'); - $this->_ci->LehreinheitModel->addJoin('public.tbl_mitarbeiter', 'lema.mitarbeiter_uid = tbl_mitarbeiter.mitarbeiter_uid'); - $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrform', 'tbl_lehrform.lehrform_kurzbz = tbl_lehreinheit.lehrform_kurzbz'); - - $this->_ci->MitarbeiterModel->db->group_start(); - - foreach ($query_words as $word) - { - $this->_ci->LehreinheitModel->db->group_start(); - $this->_ci->LehreinheitModel->db->where('lema.mitarbeiter_uid ILIKE', "%" . $word . "%"); - $this->_ci->LehreinheitModel->db->or_where('lvb.gruppe_kurzbz ILIKE', "%" . $word . "%"); - $this->_ci->LehreinheitModel->db->or_where('tbl_studiengang.kurzbzlang ILIKE', "%" . $word . "%"); - $this->_ci->LehreinheitModel->db->or_where('lvb.verband ILIKE', "%" . $word . "%"); - $this->_ci->LehreinheitModel->db->or_where('lvb.gruppe ILIKE', "%" . $word . "%"); - $this->_ci->LehreinheitModel->db->or_where('lehrfach.bezeichnung ILIKE', "%" . $word . "%"); - - if (is_numeric($word)) - { - $this->_ci->LehreinheitModel->db->or_where('tbl_studiengang.studiengang_kz', $word); - $this->_ci->LehreinheitModel->db->or_where('lvb.semester', $word); - } - $this->_ci->LehreinheitModel->db->group_end(); - - } - $this->_ci->LehreinheitModel->db->group_end(); - $this->_ci->LehreinheitModel->db->where('tbl_lehreinheit.studiensemester_kurzbz = \'SS2025\''); - $this->_ci->LehreinheitModel->db->where(array('tbl_lehrform.verplanen' => true)); - - $result = $this->_ci->LehreinheitModel->load(); - - $this->terminateWithSuccess(hasData($result) ? getData($result) : array()); - } - - public function getByStg() + public function getCourses() { $this->_ci->form_validation->set_data($_POST); - $this->_ci->form_validation->set_rules('studiengaenge[]',"studiengaenge","required"); $this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required"); if($this->_ci->form_validation->run() === FALSE) $this->terminateWithValidationErrors($this->_ci->form_validation->error_array()); - $studiengaenge = $this->input->post('studiengaenge'); - $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + $studiensemester_kurzbz = $this->_ci->input->post('studiensemester_kurzbz', TRUE); + $filter = $this->_checkFilter(self::ALLOWED_COURSE_FILTER); + + $this->_getBasePlan($studiensemester_kurzbz); + + $this->_ci->LehreinheitModel->db->group_start(); + if (isset($filter->stg)) + $this->_addStgWhere($filter->stg); + + if (isset($filter->uid)) + { + $uid_array = (array) $filter->uid; + $this->_ci->LehreinheitModel->db->or_where_in('tbl_benutzer.uid', $uid_array); + } + + $this->_ci->LehreinheitModel->db->group_end(); + + $this->_ci->LehreinheitModel->addOrder('lehreinheit_id'); + $result = $this->_ci->LehreinheitModel->load(); + $result = hasData($result) ? getData($result) : array(); + $this->terminateWithSuccess($this->_mapEvents($result)); + } + + private function _getBasePlan($studiensemester_kurzbz) + { $this->_ci->LehreinheitModel->addSelect(' tbl_lehreinheit.lehreinheit_id, tbl_lehreinheit.lvnr, @@ -142,6 +96,15 @@ class Coursepicker extends FHCAPI_Controller $this->_ci->LehreinheitModel->addJoin('public.tbl_benutzer', 'ma.mitarbeiter_uid = tbl_benutzer.uid'); $this->_ci->LehreinheitModel->addJoin('public.tbl_person', 'tbl_benutzer.person_id = tbl_person.person_id'); + $this->_ci->LehreinheitModel->db->group_start(); + $this->_ci->LehreinheitModel->db->where('tbl_lehrform.verplanen', true); + $this->_ci->LehreinheitModel->db->where('tbl_lehreinheit.studiensemester_kurzbz', $studiensemester_kurzbz); + $this->_ci->LehreinheitModel->db->group_end(); + + } + + private function _addStgWhere($studiengaenge) + { $this->_ci->LehreinheitModel->db->group_start(); $first = true; foreach ($studiengaenge as $studiengang) @@ -165,14 +128,10 @@ class Coursepicker extends FHCAPI_Controller $this->_ci->LehreinheitModel->db->group_end(); } $this->_ci->LehreinheitModel->db->group_end(); + } - $result = $this->_ci->LehreinheitModel->loadWhere(array( - 'tbl_lehrform.verplanen' => true, - 'tbl_lehreinheit.studiensemester_kurzbz' => $studiensemester_kurzbz - )); - - $result = hasData($result) ? getData($result) : array(); - + private function _mapEvents($result) + { $lehreinheit_ids = array_values(array_unique(array_column($result, 'lehreinheit_id'))); $offen_map = array(); @@ -281,10 +240,8 @@ class Coursepicker extends FHCAPI_Controller $group->verplant = $this->_formatArr($group->verplant); $group->offenestunden = $this->_formatArr($group->offenestunden); } - - $this->terminateWithSuccess(array_values($grouped)); + return array_values($grouped); } - private function _formatArr($arr) { $values = array_values(array_unique($arr)); @@ -296,5 +253,24 @@ class Coursepicker extends FHCAPI_Controller return $formatted; } + private function _checkFilter($filters) + { + $filter_valid = false; + $filter_object = new stdClass(); + foreach ($filters as $filter) + { + if ($this->_ci->input->post($filter)) + { + $filter_valid = true; + $filter_object->$filter = $this->_ci->input->post($filter); + } + } + + if (!$filter_valid) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + return $filter_object; + } + } diff --git a/public/js/api/factory/tempus/coursepicker.js b/public/js/api/factory/tempus/coursepicker.js index 92ff4fa6b..80b201a00 100644 --- a/public/js/api/factory/tempus/coursepicker.js +++ b/public/js/api/factory/tempus/coursepicker.js @@ -1,16 +1,9 @@ export default { - search(query) { - return { - method: 'get', - url: 'api/frontend/v1/tempus/coursepicker/search', - params: { query } - }; - }, - getByStg(studiengaenge, studiensemester_kurzbz) { + getCourses(filter, studiensemester_kurzbz) { return { method: 'post', - url: 'api/frontend/v1/tempus/coursepicker/getByStg', - params: { studiengaenge, studiensemester_kurzbz } + url: 'api/frontend/v1/tempus/coursepicker/getCourses', + params: { ...filter, studiensemester_kurzbz } }; }, diff --git a/public/js/components/Tempus/Coursepicker.js b/public/js/components/Tempus/Coursepicker.js index 95b8bbb5c..a56a386af 100644 --- a/public/js/components/Tempus/Coursepicker.js +++ b/public/js/components/Tempus/Coursepicker.js @@ -14,6 +14,10 @@ export default { type: Array, default: [], }, + lecturers: { + type: Array, + default: [], + }, studiensemester: { type: String, default: null @@ -26,7 +30,8 @@ export default { allCourses: [], sortBy: null, multiWeekIds: new Set(), - favorites: new Set() + favorites: new Set(), + filter: {} } }, computed: { @@ -86,32 +91,45 @@ export default { studiengaenge: { deep: true, handler(val) { - this.searchparam = ''; - this.loadCoursesByStg(val); + this.loadCourses(); + } + }, + lecturers: { + deep: true, + handler() { + this.loadCourses(); } }, studiensemester() { if (this.studiengaenge) - this.loadCoursesByStg(this.studiengaenge); + this.loadCourses(); }, }, methods: { - async loadCoursesByStg(stg) { - if (stg.length <= 0) - { - this.allCourses = []; - return; + async loadCourses() + { + const hasLektoren = this.lecturers.length > 0; + const hasStg = this.studiengaenge.length > 0; + + this.filter = {}; + if (hasLektoren) + this.filter.uid = this.lecturers; + + if (hasStg) { + this.filter.stg = this.studiengaenge.map( + ({ studiengang_kz, semester, orgform_kurzbz }) => ({ + studiengang_kz, + semester, + orgform_kurzbz, + }), + ); } - let payload = stg.map(({ studiengang_kz, semester, orgform_kurzbz }) => ({ - studiengang_kz, - semester, - orgform_kurzbz - })); - - this.$api.call(ApiCoursePicker.getByStg(payload, this.studiensemester)) + if (Object.keys(this.filter).length === 0) + return this.allCourses = []; + this.$api.call(ApiCoursePicker.getCourses(this.filter, this.studiensemester)) .then(result => { - this.allCourses = result.data.map(e => ({ + this.allCourses = result?.data?.map(e => ({ lehreinheit_id: e.lehreinheit_id, lektoren: e.lektoren, raumtyp: e.raumtyp, @@ -177,7 +195,7 @@ export default { }, reload() { - this.loadCoursesByStg(this.studiengaenge); + this.loadCourses(); }, toggleMultiWeek(course) { @@ -253,7 +271,7 @@ export default { -
+
{{$p.t('lehre', 'cptitleempty')}} {{$p.t('lehre', 'cpempty')}}
diff --git a/public/js/components/Tempus/Filters/LectureSelection.js b/public/js/components/Tempus/Filters/LectureSelection.js index a25856b86..d08a35774 100644 --- a/public/js/components/Tempus/Filters/LectureSelection.js +++ b/public/js/components/Tempus/Filters/LectureSelection.js @@ -47,6 +47,10 @@ export default { Zeitwünsche
+
+ + Course Picker +
diff --git a/public/js/components/Tempus/Filters/searchbarOptions.js b/public/js/components/Tempus/Filters/searchbarOptions.js index 42150ed41..bf909064e 100644 --- a/public/js/components/Tempus/Filters/searchbarOptions.js +++ b/public/js/components/Tempus/Filters/searchbarOptions.js @@ -43,6 +43,14 @@ export function getTempusSearchbarOptions(self) self.addToFilter(data, 'mitarbeiter'); } }, + { + label: "zum Course Picker hinzufügen", + icon: "fas fa-plus", + type: "function", + action: (data) => { + self.addToCoursePicker(data); + } + }, ] }, } diff --git a/public/js/components/Tempus/Tempus.js b/public/js/components/Tempus/Tempus.js index 360c198d7..b064025c0 100644 --- a/public/js/components/Tempus/Tempus.js +++ b/public/js/components/Tempus/Tempus.js @@ -181,21 +181,11 @@ export default { .filter((lecture) => lecture.showEvents) .map((lecture) => lecture.uid); }, - visibleStatusOptions() { - return Object.entries(this.visibleStatusArray).map(([key, label]) => ({ - key, - label, - })); - }, - visibleStatusValue() { - if (this.visibleStatus.includes("all")) - return this.visibleStatusOptions.filter( - (visibleStatus) => visibleStatus.key === "all", - ); - return this.visibleStatus.map((status) => ({ - key: status, - label: this.visibleStatusArray[status], - })); + courseLecturers() { + if (!this.lecturers.length) return []; + return this.lecturers + .filter((lecture) => lecture.showCoursePicker) + .map((lecture) => lecture.uid); }, keyboardShortcuts() { return getTempusShortcuts(this); @@ -276,12 +266,11 @@ export default { .call(ApiKalender.syncToStudent(orig.kalender_id)) .then(() => this.$refs.calendar.resetEventLoader()); }, - setOrt: function (data) { + setOrt (data) { this.ort_kurzbz = data.ort_kurzbz; this.rooms = [{ ort_kurzbz: data.ort_kurzbz }]; }, onSelectVerbandAndClose(payload) { - console.log(payload); this.onSelectVerband(payload); bootstrap.Offcanvas.getOrCreateInstance(this.$refs.verbandMenu).hide(); }, @@ -307,41 +296,62 @@ export default { ]; } }, - setEmp: function (data) { + addToCoursePicker(data) + { const uid = data.uid; - const label = data.name; + let lecturer = this.lecturers.find((lecture) => lecture.uid === uid); - for (const lect of this.lecturers) delete this.overlayCache[lect.uid]; + if (!lecturer) + { + this.addToFilter(data, 'mitarbeiter'); + lecturer = this.lecturers.find((lecture) => lecture.uid === uid); - this.lecturers = [ + if (lecturer) { - uid, - label, - showEvents: true, - overlays: { blocks: true, wishes: true }, - }, - ]; + lecturer.overlays = { + blocks: false, + wishes: false + } + } + } - this.$refs.calendar.resetEventLoader(); - if (this.lastRange) this.handleRange(this.lastRange); + if (lecturer) + { + lecturer.showCoursePicker = true + } }, - addToFilter: function (filter, type) { - if (type === "ort") { + + addToFilter (filter, type) { + if (type === "ort") + { const ort_kurzbz = filter.ort_kurzbz; - if (!this.rooms.some((room) => room.ort_kurzbz === ort_kurzbz)) { + if (!this.rooms.some((room) => room.ort_kurzbz === ort_kurzbz)) + { this.rooms.push({ ort_kurzbz }); } - } else if (type === "mitarbeiter") { + } + else if (type === "mitarbeiter") + { const uid = filter.uid; const label = filter.name; - if (!this.lecturers.some((l) => l.uid === uid)) { + + let lecturer = this.lecturers.find((lecture) => lecture.uid === uid); + + if (!lecturer) + { this.lecturers.push({ uid, label, showEvents: true, overlays: { blocks: true, wishes: true }, + showCoursePicker: false }); } + else + { + lecturer.showEvents = true; + lecturer.overlays = { blocks: true, wishes: true }; + } } this.$refs.calendar.resetEventLoader(); @@ -1175,21 +1185,10 @@ export default {
- -
+ class="d-flex gap-1 py-1" + data-cy="previewRoleOptionsHolder" + >