From ab5294de2fee7271208f1e705156be960afadd43 Mon Sep 17 00:00:00 2001 From: ma0048 Date: Wed, 1 Apr 2026 10:53:31 +0200 Subject: [PATCH] stylingaenderungen coursepicker umgebaut, keine backend suche mehr hinzugefuegt: - resizeHanlder funktion - broadcastchannel postMessage "dropped" - tbl_kalender_status column bezeichnung_mehrsprachig - tbl_kalender_status column sort --- .../api/frontend/v1/tempus/Config.php | 19 +- .../api/frontend/v1/tempus/Coursepicker.php | 164 ++++++++++++- application/libraries/KalenderLib.php | 7 +- public/css/Tempus.css | 44 ++-- public/js/api/factory/tempus/coursepicker.js | 12 +- public/js/apps/Tempus.js | 1 + public/js/components/Calendar/Base.js | 8 +- public/js/components/Calendar/Base/Grid.js | 3 +- public/js/components/Calendar/Tempus.js | 69 +++--- public/js/components/Tempus/Coursepicker.js | 167 +++++++++---- public/js/components/Tempus/ParkingSlot.js | 2 +- public/js/components/Tempus/Tempus.js | 227 ++++++++++++++---- public/js/directives/drop.js | 2 + system/dbupdate_3.4/46975_tempus.php | 16 +- 14 files changed, 553 insertions(+), 188 deletions(-) diff --git a/application/controllers/api/frontend/v1/tempus/Config.php b/application/controllers/api/frontend/v1/tempus/Config.php index 0bea310c3..27a4958cb 100644 --- a/application/controllers/api/frontend/v1/tempus/Config.php +++ b/application/controllers/api/frontend/v1/tempus/Config.php @@ -27,6 +27,11 @@ class Config extends FHCAPI_Controller public function get() { + + $language = getUserLanguage() == 'German' ? 0 : 1; + + $this->_ci->KalenderStatusModel->addSelect('*, array_to_json(bezeichnung_mehrsprachig::varchar[])->>' . $language .' AS status'); + $this->_ci->KalenderStatusModel->addOrder('sort'); $visible_status = $this->_ci->KalenderStatusModel->load(); $visible_status = getData($visible_status); @@ -34,28 +39,32 @@ class Config extends FHCAPI_Controller $config['visible_status'] = [ "type" => "select", "label" => $this->p->t('ui', 'status'), - "multiple" => true, "value" => 'all' ]; + + foreach ($visible_status as $status) { - $config['visible_status']['options'][$status->status_kurzbz] = $status->status_kurzbz; + $config['visible_status']['options'][$status->status_kurzbz] = $status->status; } $this->terminateWithSuccess($config); } public function getHeader() { + $language = getUserLanguage() == 'German' ? 0 : 1; + + $this->_ci->KalenderStatusModel->addSelect('*, array_to_json(bezeichnung_mehrsprachig::varchar[])->>' . $language .' AS status'); + $this->_ci->KalenderStatusModel->addOrder('sort'); $visible_status = $this->_ci->KalenderStatusModel->load(); $visible_status = getData($visible_status); - - $config['visible_status']['all'] = 'all'; + $config['visible_status']['all'] = 'Alle'; foreach ($visible_status as $status) { - $config['visible_status'][$status->status_kurzbz] = $status->bezeichnung; + $config['visible_status'][$status->status_kurzbz] = $status->status; } $this->terminateWithSuccess($config); diff --git a/application/controllers/api/frontend/v1/tempus/Coursepicker.php b/application/controllers/api/frontend/v1/tempus/Coursepicker.php index 0774fc300..73414c75e 100644 --- a/application/controllers/api/frontend/v1/tempus/Coursepicker.php +++ b/application/controllers/api/frontend/v1/tempus/Coursepicker.php @@ -9,6 +9,7 @@ class Coursepicker extends FHCAPI_Controller { parent::__construct([ 'search' => self::PERM_LOGGED, + 'getByStg' => self::PERM_LOGGED ]); $this->_ci = &get_instance(); @@ -18,9 +19,7 @@ class Coursepicker extends FHCAPI_Controller $this->_ci->load->model('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel'); - $this->loadPhrases([ - 'ui' - ]); + $this->loadPhrases(['ui']); } public function search() @@ -93,4 +92,163 @@ class Coursepicker extends FHCAPI_Controller $this->terminateWithSuccess(hasData($result) ? getData($result) : array()); } + + public function getByStg() + { + //TODO check einbauen ob studiensemester und stg vorhanden ist + $stg = $this->input->get('stg'); + $studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz'); + if (is_null($stg) || is_null($studiensemester_kurzbz)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $this->_ci->LehreinheitModel->addSelect(' + tbl_lehreinheit.lehreinheit_id, + tbl_lehreinheit.unr, + 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, + ma.kurzbz AS lektor, + tbl_person.vorname, + tbl_person.nachname, + 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 ma', 'lema.mitarbeiter_uid = ma.mitarbeiter_uid'); + $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrform', 'tbl_lehrform.lehrform_kurzbz = tbl_lehreinheit.lehrform_kurzbz'); + $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'); + + $result = $this->_ci->LehreinheitModel->loadWhere(array( + 'tbl_lehrform.verplanen' => true, + 'tbl_studiengang.studiengang_kz' => $stg, + 'tbl_lehreinheit.studiensemester_kurzbz' => $studiensemester_kurzbz + )); + + $result = hasData($result) ? getData($result) : array(); + $grouped = array(); + + foreach ($result as $row) + { + $unr = $row->unr; + if (!isset($grouped[$unr])) + { + $grouped[$unr] = (object)array( + 'unr' => $row->unr, + 'lehrfach_id' => $row->lehrfach_id, + 'lehrfach_bez' => $row->lehrfach_bez, + 'lehrfach_farbe' => $row->lehrfach_farbe, + 'studiengang_kz' => $row->studiengang_kz, + 'studiengang' => $row->studiengang, + 'semester' => $row->semester, + 'verband' => $row->verband, + 'gruppe' => $row->gruppe, + 'gruppe_kurzbz' => $row->gruppe_kurzbz, + 'raumtyp' => $row->raumtyp, + 'raumtypalternativ' => $row->raumtypalternativ, + 'anmerkung' => $row->anmerkung, + 'studiensemester_kurzbz' => $row->studiensemester_kurzbz, + 'fachbereich_kurzbz' => isset($row->fachbereich_kurzbz) ? $row->fachbereich_kurzbz : null, + 'lektoren' => array(), + 'lehreinheit_id' => array(), + 'lvnr' => array(), + 'lehrfach' => array(), + 'lehrform' => array(), + 'stundenblockung' => array(), + 'wochenrythmus' => array(), + 'planstunden' => array(), + 'start_kw' => array(), + 'verplant' => array(), + 'offenestunden' => array(), + 'lehrverband' => array(), + 'lem' => array(), + 'verplant_gesamt' => 0, + ); + } + + $group = $grouped[$unr]; + + $group->lektoren[$row->lektor_uid] = (object)array( + 'uid' => $row->lektor_uid, + 'kurzbz' => trim($row->lektor), + 'name' => $row->vorname . ' ' . $row->nachname, + ); + + $group->lehreinheit_id[] = $row->lehreinheit_id; + $group->lvnr[] = $row->lvnr; + $group->lehrfach[] = $row->lehrfach; + $group->lehrform[] = $row->lehrform; + $group->stundenblockung[] = $row->stundenblockung; + $group->wochenrythmus[] = $row->wochenrythmus; + $group->planstunden[] = $row->planstunden; + $group->start_kw[] = $row->start_kw; + $group->verplant[] = isset($row->verplant) ? $row->verplant : 0; + $group->offenestunden[] = isset($row->offenestunden) ? $row->offenestunden : 0; + $group->verplant_gesamt += isset($row->verplant) ? $row->verplant : 0; + + $lvb = $row->studiengang . '-' . $row->semester; + + if ($row->verband != '' && $row->verband != ' ' && $row->verband != '0' && $row->verband != null) + $lvb .= $row->verband; + + if ($row->gruppe != '' && $row->gruppe != ' ' && $row->gruppe != '0' && $row->gruppe != null) + $lvb .= $row->gruppe; + + $group->lehrverband[] = ($row->gruppe_kurzbz != '' && $row->gruppe_kurzbz != null) ? $row->gruppe_kurzbz : $lvb; + + $group->lem[] = array( + 'lehreinheit_id' => $row->lehreinheit_id, + 'mitarbeiter_uid' => $row->lektor_uid, + ); + } + + foreach ($grouped as $group) + { + $group->lektoren = array_values($group->lektoren); + $group->lehrverband = array_values(array_unique($group->lehrverband)); + $group->lehrfach = $this->_formatArr($group->lehrfach); + $group->lehrform = $this->_formatArr($group->lehrform); + $group->stundenblockung = $this->_formatArr($group->stundenblockung); + $group->wochenrythmus = $this->_formatArr($group->wochenrythmus); + $group->planstunden = $this->_formatArr($group->planstunden); + $group->start_kw = $this->_formatArr($group->start_kw); + $group->verplant = $this->_formatArr($group->verplant); + $group->offenestunden = $this->_formatArr($group->offenestunden); + } + + $this->terminateWithSuccess(array_values($grouped)); + } + + private function _formatArr($arr) + { + $values = array_values(array_unique($arr)); + $formatted = implode(' ', $values); + + if (count($formatted) > 1) + $formatted .= ' ?'; + + return $formatted; + } + + } diff --git a/application/libraries/KalenderLib.php b/application/libraries/KalenderLib.php index bd0bd71cf..5e33d40e1 100644 --- a/application/libraries/KalenderLib.php +++ b/application/libraries/KalenderLib.php @@ -5,9 +5,6 @@ if (! defined("BASEPATH")) exit("No direct script access allowed"); class KalenderLib { private $_ci; - /** - * Loads model OrganisationseinheitModel - */ public function __construct() { $this->_ci =& get_instance(); @@ -453,8 +450,8 @@ class KalenderLib { return $this->_ci->KalenderOrtModel->insert( array ( - 'kalender_id'=>$kalender_id, - 'ort_kurzbz'=>$ort_kurzbz + 'kalender_id' => $kalender_id, + 'ort_kurzbz' => $ort_kurzbz ) ); } diff --git a/public/css/Tempus.css b/public/css/Tempus.css index 7e88e0a42..66c4562a7 100644 --- a/public/css/Tempus.css +++ b/public/css/Tempus.css @@ -82,12 +82,32 @@ body { #parkingslot { border: 1px dashed; - max-height: 400px; + min-height: 5vh; + max-height: 15vh; color: #AAAAAA; text-align: center; font-size: large; - margin-top: 20px; - padding-top: 0.5rem; + margin-top: 1.25rem; + overflow-y: auto; + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; +} + +.course-picker { + border: 1px dashed #AAAAAA; + display: flex; + flex-direction: column; + flex: 1 1 0; + min-height: 0; +} + +.course-picker-row { + padding: 0.5rem; + margin-bottom: 0.5rem; + border: 1px solid var(--bs-border-color); + background-color: var(--bs-tertiary-bg); } .parkingevent { @@ -148,30 +168,16 @@ body { .lecture-selection { border: 1px dashed #AAAAAA; margin-bottom: 0.5rem; - max-height: 300px; + max-height: 20vh; overflow-y: auto; display: flex; flex-direction: column; } -.course-picker { - border: 1px dashed #AAAAAA; - height: 400px; - max-height: 400px; - display: flex; - flex-direction: column; -} -.course-picker-row { - padding: 0.5rem; - margin-bottom: 0.5rem; - border: 1px solid var(--bs-border-color); - background-color: var(--bs-tertiary-bg); -} - .room-selection { border: 1px dashed #AAAAAA; margin-bottom: 0.5rem; - padding: 0.5rem 0.0rem 0.5rem 0.5rem; + padding: 0.5rem 0 0.5rem 0.5rem; } .btn-link.text-danger { diff --git a/public/js/api/factory/tempus/coursepicker.js b/public/js/api/factory/tempus/coursepicker.js index 637caf732..82e1a6965 100644 --- a/public/js/api/factory/tempus/coursepicker.js +++ b/public/js/api/factory/tempus/coursepicker.js @@ -3,7 +3,15 @@ export default { return { method: 'get', url: 'api/frontend/v1/tempus/coursepicker/search', - params: { query } + params: { query } }; - } + }, + getByStg(stg, studiensemester_kurzbz) { + return { + method: 'get', + url: 'api/frontend/v1/tempus/coursepicker/getByStg', + params: { stg, studiensemester_kurzbz } + }; + }, + }; diff --git a/public/js/apps/Tempus.js b/public/js/apps/Tempus.js index 1faf50956..0cf61f533 100644 --- a/public/js/apps/Tempus.js +++ b/public/js/apps/Tempus.js @@ -39,4 +39,5 @@ app } }) .use(Phrasen) + .directive('tooltip', primevue.tooltip) .mount('#main'); diff --git a/public/js/components/Calendar/Base.js b/public/js/components/Calendar/Base.js index 7b770e55c..b83bf722c 100644 --- a/public/js/components/Calendar/Base.js +++ b/public/js/components/Calendar/Base.js @@ -63,7 +63,8 @@ export default { return () => true; }), hasDragoverFunc: Vue.computed(() => this.onDragover), - mode: Vue.computed(() => this.mode) + mode: Vue.computed(() => this.mode), + onResize: Vue.computed(() => this.onResize || null), }; }, props: { @@ -121,7 +122,8 @@ export default { dropableEvents: [Boolean, Array, Function], resizableEvents: [Boolean, Array, Function], onDragover: Function, - onDrop: Function + onDrop: Function, + onResize: Function }, emits: [ "click:next", @@ -212,7 +214,7 @@ export default { }, watch: { sDate(n, o) { - if (this.sDate.isValid && !this.sDate.hasSame(this.internalDate, 'day')) + if (this.sDate.isValid && (!this.internalDate || !this.sDate.hasSame(this.internalDate, 'day'))) this.internalDate = this.sDate; }, sMode() { diff --git a/public/js/components/Calendar/Base/Grid.js b/public/js/components/Calendar/Base/Grid.js index 0c3604669..841908004 100644 --- a/public/js/components/Calendar/Base/Grid.js +++ b/public/js/components/Calendar/Base/Grid.js @@ -18,6 +18,7 @@ export default { originalBackgrounds: "backgrounds", dropAllowed: "dropAllowed", onDrop: "onDrop", + onResize: "onResize", timeGrid: { from: "timeGrid", default: () => [] @@ -454,7 +455,7 @@ export default { if (!orig || !newStart || !newEnd) return; - this.onDrop?.({ + this.onResize?.({ item: [{ type: 'kalender', id: orig.kalender_id, orig }], start: newStart, end: newEnd diff --git a/public/js/components/Calendar/Tempus.js b/public/js/components/Calendar/Tempus.js index ffdce126a..90a25dcc9 100644 --- a/public/js/components/Calendar/Tempus.js +++ b/public/js/components/Calendar/Tempus.js @@ -54,13 +54,18 @@ export default { extraBackgrounds: { type: Array, default: () => [] - } + }, + visibleStatus: { + type: Array, + default: () => ['all'] + }, }, emits: [ "update:date", "update:mode", "update:range", - "drop" + "drop", + "resize" ], data() { @@ -80,8 +85,7 @@ export default { } }, teachingunits: null, - visibleStatusArray: [], - visibleStatus: [] + showRaster: true, }; }, computed: { @@ -132,25 +136,6 @@ export default { }, }, methods: { - toggleStatus(status) { - if (status === 'all') - { - this.visibleStatus = ['all']; - return; - } - - this.visibleStatus = this.visibleStatus.filter(visibleStatus => visibleStatus !== 'all'); - - let found = this.visibleStatus.indexOf(status); - - if (found === -1) - this.visibleStatus.push(status); - else - this.visibleStatus.splice(found, 1); - - if (this.visibleStatus.length < 1) - this.visibleStatus.push('all'); - }, eventStyle(event) { if (!event.farbe) return undefined; @@ -163,6 +148,9 @@ export default { ondrop(payload){ this.$emit('drop', payload); }, + onresize(payload){ + this.$emit('resize', payload); + }, resetEventLoader() { this.reset(); }, @@ -177,6 +165,14 @@ export default { context.emit('update:lv', newValue); }); + const bcc = new BroadcastChannel('fhc-dnd'); + bcc.onmessage = e => { + if (e.data === 'dropped') + { + reset() + } + }; + return { rangeInterval, events, @@ -195,11 +191,6 @@ export default { end: el.ende })); }); - this.$api.call(ApiTempusConfig.getHeader()) - .then(res => { - this.visibleStatusArray = res.data.visible_status - this.visibleStatus = ['all'] - }); }, template: /* html */` ` } diff --git a/public/js/components/Tempus/Coursepicker.js b/public/js/components/Tempus/Coursepicker.js index fe51800b1..98a6a17fe 100644 --- a/public/js/components/Tempus/Coursepicker.js +++ b/public/js/components/Tempus/Coursepicker.js @@ -9,54 +9,96 @@ export default { directives: { draggable }, + props: { + stg: { + type: [String, Number], + default: null, + }, + studiensemester: { + type: String, + default: null + }, + }, + emits: ['select-lecturer', 'select-kw'], data() { return { searchparam: '', - courses: null, + allCourses: [], abortController: null, } }, - methods: { - async loadCourses() { - - const query = (this.searchparam ?? '').trim(); - + computed: { + courses() { + const query = (this.searchparam ?? '').trim().toLowerCase(); if (!query) - { - this.courses = []; + return this.allCourses; + + return this.allCourses.filter(course => + course.showname.toLowerCase().includes(query) || + course.lektoren?.some(l => + l.name.toLowerCase().includes(query) || + l.kurzbz.toLowerCase().includes(query) + ) + ); + } + }, + watch: { + stg(val) { + this.searchparam = ''; + this.loadCoursesByStg(val); + }, + studiensemester() { + if (this.stg) + this.loadCoursesByStg(this.stg); + }, + }, + methods: { + async loadCoursesByStg(stg) { + if (!stg) { + this.allCourses = []; return; } - if (query.length < 3) - return; - - if (this.abortController) - { - this.abortController.abort(); - } - - this.abortController = new AbortController(); - const signal = this.abortController.signal; - - this.$api.call(ApiCoursePicker.search(query), { signal }) + this.$api.call(ApiCoursePicker.getByStg(this.stg, this.studiensemester)) .then(result => { - this.courses = result.data.map(entry => ({ - lehreinheit_id: entry.lehreinheit_id, - lektoren: entry.lektor, - studiengang: entry.studiengang, - semester: entry.semester, - stundenblockung: entry.stundenblockung, - wochenrythmus: entry.wochenrythmus, - showname: `${entry.lehrfach} ${entry.lehrform}`, + this.allCourses = result.data.map(e => ({ + lvnr: e.lvnr.join(' '), + unr: e.unr, + lektoren: e.lektoren, + lehrfach_id: e.lehrfach_id, + studiengang_kz: e.studiengang_kz, + fachbereich_kurzbz: e.fachbereich_kurzbz, + semester: e.semester, + verband: e.verband, + gruppe: e.gruppe, + gruppe_kurzbz: e.gruppe_kurzbz, + raumtyp: e.raumtyp, + raumtypalternativ: e.raumtypalternativ, + semesterstunden: e.planstunden, + stundenblockung: e.stundenblockung, + wochenrythmus: e.wochenrythmus, + verplant: e.verplant, + offenestunden: e.offenestunden, + start_kw: e.start_kw, + anmerkung: e.anmerkung, + studiensemester_kurzbz: e.studiensemester_kurzbz, + lehrfach: e.lehrfach, + lehrform: e.lehrform, + lehrfach_bez: e.lehrfach_bez, + lehrfach_farbe: e.lehrfach_farbe, + lehrverband: e.lehrverband.join(' '), + lehreinheit_id: e.lehreinheit_id, + lem: e.lem, + showname: `${e.lehrfach} ${e.lehrform}`, orig: { type: 'lehreinheit', - lehreinheit_id: entry.lehreinheit_id, - blockung: entry.stundenblockung, - entry, + lehreinheit_id: e.lehreinheit_id[0], + blockung: e.stundenblockung, + entry: e, } })); }) - .catch(this.$fhcAlert.handleSystemError) + .catch(this.$fhcAlert.handleSystemError); }, dragLehreinheitCollection(course) { const orig = course.orig; @@ -80,19 +122,25 @@ export default { course.mode = 'multi'; break } + }, + selectLecturer: function(lektor) { + this.$emit('select-lecturer', lektor); } }, template: ` -
+
- -
-
+ +
+
+ Keine Lehreinheiten + Wähle einen Studiengang, um Lehreinheiten anzuzeigen. +
+
-
- {{ course.showname }} +
+ {{ course.lehrfach }} {{ course.lehrform }} + {{ course.raumtyp }}
-
- {{ course.studiengang }} - {{ course.semester }} +
+ {{ course.lehrverband }} + KW: {{ course.start_kw }} +
-
- {{ course.lektoren }} +
+ + {{ lektor.kurzbz }} +
+
+ WR: {{ course.wochenrythmus }} Bl: {{ course.stundenblockung }}
-
- WR: {{ course.wochenrythmus }} Bl: {{ course.stundenblockung }} +
+ Offen: {{ course.offenestunden }} + {{ course.semesterstunden }}
-
- Drag & Drop on Calendar -
` -} +} \ No newline at end of file diff --git a/public/js/components/Tempus/ParkingSlot.js b/public/js/components/Tempus/ParkingSlot.js index d5e632b9d..6bc7bbf95 100644 --- a/public/js/components/Tempus/ParkingSlot.js +++ b/public/js/components/Tempus/ParkingSlot.js @@ -64,7 +64,7 @@ export default { class="parkingslot" v-drop:move.kalender-collection="(evt, item) => park(evt, item)" > - + 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] })); + }, }, methods: { async openRaumauswahl(orig) { @@ -201,11 +215,14 @@ export default { this.ort_kurzbz = data.ort_kurzbz; this.$refs.calendar.resetEventLoader(); }, + onSelectVerbandAndClose(payload) { + this.onSelectVerband(payload); + bootstrap.Offcanvas.getOrCreateInstance(this.$refs.verbandMenu).hide(); + }, onSelectVerband({link, name}) { let stg = null; let semester = null; - let studiensemester_kurzbz = this.selectedStudiensemester; this.show_stg = name if (typeof link === 'number') stg = link; @@ -216,8 +233,7 @@ export default { this.stg = stg; if (semester !== null) this.semester = semester; - if (studiensemester_kurzbz) - this.studiensemester_kurzbz = studiensemester_kurzbz; + this.$refs.calendar.resetEventLoader(); }, @@ -239,12 +255,42 @@ export default { if (this.lastRange) this.handleRange(this.lastRange); }, - handleChangeDate() { - console.log("handleChangeDate"); + jumpToKw(kw) { + const num = parseInt(kw); + if (!num) + return; + + const date = luxon.DateTime.fromObject({ + weekYear: luxon.DateTime.now().setZone(this.config.timezone).weekYear, + weekNumber: num, + weekday: 1, + }, { zone: this.config.timezone }); + this.calendarDate = date.toISODate(); + }, + handleChangeDate(newDate) { + if (newDate && luxon.DateTime.isDateTime(newDate) && newDate.isValid) + this.calendarDate = newDate.toISODate(); }, handleChangeMode() { console.log("handleChangeMode") }, + toggleStatus(selected) { + if (!selected || selected.length === 0) { + this.visibleStatus = ['all']; + return; + } + const hasAll = selected.includes('all'); + const hadAll = this.visibleStatus.includes('all'); + + if (hasAll && !hadAll) + { + this.visibleStatus = ['all']; + return; + } + this.visibleStatus = selected.filter(k => k !== 'all'); + if (this.visibleStatus.length === 0) + this.visibleStatus = ['all']; + }, searchfunction(params) { return this.$api.call(ApiSearchbar.search(params)); }, @@ -309,9 +355,64 @@ export default { return calculatedEnd > lastGridEndSameDay ? lastGridEndSameDay : calculatedEnd; }, + _parseDates(start, end) + { + const startDT = luxon.DateTime.fromISO(start); + const endDT = luxon.DateTime.fromISO(end); + + if (!startDT.isValid || !endDT.isValid) + { + alert("Ungültiges Datum"); + return null; + } + + return { + startDT, + endDT, + start_time: startDT.toFormat('yyyy-MM-dd HH:mm'), + end_time: endDT.toFormat('yyyy-MM-dd HH:mm'), + }; + }, + + _updateKalenderEvent(obj, startDT, endDT, start_time, end_time, onSuccess) + { + const origStart = luxon.DateTime.fromISO(obj.orig.isostart); + const origEnd = luxon.DateTime.fromISO(obj.orig.isoend); + + if (origStart.toMillis() === startDT.toMillis() && origEnd.toMillis() === endDT.toMillis()) + return; + + const updatedInfos = { + ort_kurzbz: this.ort_kurzbz ? this.ort_kurzbz : obj.orig.ort_kurzbz, + start_time, + end_time, + }; + + this.$api.call(ApiKalender.updateKalenderEvent(obj.orig.kalender_id, updatedInfos)) + .then(() => { + if (onSuccess) + onSuccess(); + }); + }, + + resizeHandler(payload) { + const { item, start, end } = payload; + const obj = item[0]; + if (!obj?.orig?.kalender_id) + return alert("Kein gültiges Kalender-Event zum Resizen"); + + const dates = this._parseDates(start, end); + + if (!dates) + return; + + this._updateKalenderEvent(obj, dates.startDT, dates.endDT, dates.start_time, dates.end_time, () => { + this.$refs.calendar.resetEventLoader(); + }); + }, + dropHandler(payload) { const { item, start, end } = payload; - if (!item?.length) return alert("Keine Daten gedroppt"); @@ -319,18 +420,12 @@ export default { if (!obj?.type) return alert("Unbekannter Drop-Typ"); - const startDT = luxon.DateTime.fromISO(start); - const endDT = luxon.DateTime.fromISO(end); + const dates = this._parseDates(start, end); + if (!dates) return; - if (!startDT.isValid || !endDT.isValid) - return alert("Ungültiges Datum"); + const { startDT, endDT, start_time, end_time } = dates; - const start_time = startDT.toFormat('yyyy-MM-dd HH:mm'); - const end_time = endDT.toFormat('yyyy-MM-dd HH:mm'); - - - if (obj.type === 'lehreinheit') - { + if (obj.type === 'lehreinheit') { this.$api.call( ApiKalender.addKalenderEvent( obj.orig.lehreinheit_id, @@ -338,29 +433,13 @@ export default { start_time, end_time ) - ).then(() => { - this.$refs.calendar.resetEventLoader(); - }); + ); } else if (obj.type === 'kalender') { - let updatedInfos = { - ort_kurzbz: this.ort_kurzbz ? this.ort_kurzbz : obj.orig.ort_kurzbz, - start_time: start_time, - end_time: end_time - } - - this.$api.call( - ApiKalender.updateKalenderEvent( - obj.orig.kalender_id, - updatedInfos - ) - ).then(() => { - this.$refs.parking.unpark({ - type: obj.type, - id: obj.orig.kalender_id - }); - this.$refs.calendar.resetEventLoader(); + this._updateKalenderEvent(obj, startDT, endDT, start_time, end_time, () => + { + this.$refs.parking.unpark({ type: obj.type, id: obj.orig.kalender_id }); }); } else @@ -538,6 +617,12 @@ export default { this.renderers[rendertype].calendarEvent = calendarEvent; } }); + + this.$api.call(ApiTempusConfig.getHeader()) + .then(res => { + this.visibleStatusArray = res.data.visible_status; + this.visibleStatus = ['all']; + }); }, template: `
@@ -632,10 +717,42 @@ export default {
+
+
+
+ Verband +
+ +
+ +
diff --git a/public/js/directives/drop.js b/public/js/directives/drop.js index 4c50e1b8e..e7b93d9fc 100644 --- a/public/js/directives/drop.js +++ b/public/js/directives/drop.js @@ -54,10 +54,12 @@ export default { if (res instanceof Promise) { res.then(r => { bcc.postMessage('release'); + bcc.postMessage('dropped'); return r; }); } else { bcc.postMessage('release'); + bcc.postMessage('dropped'); } } diff --git a/system/dbupdate_3.4/46975_tempus.php b/system/dbupdate_3.4/46975_tempus.php index 1e7d9a89a..3b6f85355 100644 --- a/system/dbupdate_3.4/46975_tempus.php +++ b/system/dbupdate_3.4/46975_tempus.php @@ -70,18 +70,20 @@ if(!$result = @$db->db_query("SELECT kalender_id FROM lehre.tbl_kalender LIMIT 1 CREATE TABLE lehre.tbl_kalender_status ( status_kurzbz character varying(32) NOT NULL, bezeichnung text, + bezeichnung_mehrsprachig character varying(255)[] NOT NULL, + sort smallint, CONSTRAINT tbl_kalender_status_pk PRIMARY KEY (status_kurzbz) ); COMMENT ON TABLE lehre.tbl_kalender_status IS 'Calender visibility Status'; - INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'planning', E'planning'); - INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'tosync', E'tosync'); - INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'todelete', E'todelete'); - INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'visible_lektor', E'Sichtbar für Lektoren'); - INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'deleted', E'deleted'); - INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'archived', E'archived'); - INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung) VALUES (E'visible_student', E'Sichtbar für Studierende'); + INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung, bezeichnung_mehrsprachig, sort) VALUES (E'planning', E'planning', E'{\"In Planung\", \"Planning\"}', 1); + INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung, bezeichnung_mehrsprachig, sort) VALUES (E'tosync', E'tosync', E'{\"Zu synchronisieren\", \"To sync\"}', 2); + INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung, bezeichnung_mehrsprachig, sort) VALUES (E'todelete', E'todelete', E'{\"Zu löschen\", \"To delete\"}', 3); + INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung, bezeichnung_mehrsprachig, sort) VALUES (E'visible_lektor', E'Sichtbar für Lektoren', E'{\"Sichtbar für Lektoren\", \"Visible for lecturers\"}', 4); + INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung, bezeichnung_mehrsprachig, sort) VALUES (E'deleted', E'deleted', E'{\"Gelöscht\", \"Deleted\"}', 5); + INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung, bezeichnung_mehrsprachig, sort) VALUES (E'archived', E'archived', E'{\"Archiviert\", \"Archived\"}', 6); + INSERT INTO lehre.tbl_kalender_status (status_kurzbz, bezeichnung, bezeichnung_mehrsprachig, sort) VALUES (E'visible_student', E'Sichtbar für Studierende', E'{\"Sichtbar für Studierende\", \"Visible for students\"}', 7); ALTER TABLE lehre.tbl_kalender ADD CONSTRAINT tbl_kalender_status_fk FOREIGN KEY (status_kurzbz) REFERENCES lehre.tbl_kalender_status (status_kurzbz) MATCH FULL