From 38424bc875d6639953ea546aa3bb8c1d55866b1e Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Tue, 29 Apr 2025 14:36:40 +0200 Subject: [PATCH] serientermin anlegen mitarbeiter; deadline overview mitarbeiter; --- application/controllers/Cis/Abgabetool.php | 23 +- .../controllers/api/frontend/v1/Lehre.php | 115 +++++++++- .../models/education/Paabgabe_model.php | 30 +++ .../models/education/Projektarbeit_model.php | 21 +- public/js/api/lehre.js | 16 ++ public/js/apps/Dashboard/Fhc.js | 7 + .../Cis/Abgabetool/AbgabeMitarbeiterDetail.js | 173 ++++----------- .../Cis/Abgabetool/AbgabetoolMitarbeiter.js | 198 +++++++++++++++--- .../Cis/Abgabetool/DeadlineOverview.js | 151 +++++++++++++ system/phrasesupdate.php | 182 +++++++++++++++- 10 files changed, 750 insertions(+), 166 deletions(-) create mode 100644 public/js/components/Cis/Abgabetool/DeadlineOverview.js diff --git a/application/controllers/Cis/Abgabetool.php b/application/controllers/Cis/Abgabetool.php index e7d183f04..1895f7472 100644 --- a/application/controllers/Cis/Abgabetool.php +++ b/application/controllers/Cis/Abgabetool.php @@ -16,7 +16,8 @@ class Abgabetool extends Auth_Controller 'index' => self::PERM_LOGGED, 'getStudentProjektarbeitAbgabeFile' => self::PERM_LOGGED, 'Mitarbeiter' => self::PERM_LOGGED, - 'Student' => self::PERM_LOGGED + 'Student' => self::PERM_LOGGED, + 'Deadlines' => self::PERM_LOGGED ]); } @@ -43,7 +44,7 @@ class Abgabetool extends Auth_Controller 'uid'=>getAuthUID(), ); - $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Abgabetool']); + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'AbgabetoolStudent']); } public function Mitarbeiter() @@ -53,7 +54,17 @@ class Abgabetool extends Auth_Controller 'uid'=>getAuthUID(), ); - $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Abgabetool']); + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'AbgabetoolMitarbeiter']); + } + + public function Deadlines() + { + + $viewData = array( + 'uid'=>getAuthUID(), + ); + + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'DeadlinesOverview']); } @@ -66,7 +77,7 @@ class Abgabetool extends Auth_Controller $student_uid = $this->_ci->input->get('student_uid'); if (!isset($paabgabe_id) || isEmptyString($paabgabe_id) || !isset($student_uid) || isEmptyString($student_uid)) - $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + $this->terminateWithJsonError($this->p->t('global', 'wrongParameters'), 'general'); $this->_ci->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); @@ -88,10 +99,10 @@ class Abgabetool extends Auth_Controller readfile($file_path); // read file content to output buffer } else { - $this->terminateWithError('File not found'); + $this->terminateWithJsonError('File not found'); } } else { - $this->terminateWithError('Keine Zuordnung!'); + $this->terminateWithJsonError('Keine Zuordnung!'); } } } diff --git a/application/controllers/api/frontend/v1/Lehre.php b/application/controllers/api/frontend/v1/Lehre.php index 375551e7a..0ec2456f5 100644 --- a/application/controllers/api/frontend/v1/Lehre.php +++ b/application/controllers/api/frontend/v1/Lehre.php @@ -45,7 +45,9 @@ class Lehre extends FHCAPI_Controller 'postStudentProjektarbeitEndupload' => self::PERM_LOGGED, 'getMitarbeiterProjektarbeiten' => self::PERM_LOGGED, 'postProjektarbeitAbgabe' => self::PERM_LOGGED, - 'deleteProjektarbeitAbgabe' => self::PERM_LOGGED + 'deleteProjektarbeitAbgabe' => self::PERM_LOGGED, + 'postSerientermin' => self::PERM_LOGGED, + 'fetchDeadlines' => self::PERM_LOGGED // TODO: mitarbeiter recht prüfen ]); $this->load->library('PhrasesLib'); @@ -556,5 +558,116 @@ class Lehre extends FHCAPI_Controller $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); } + + /** + * endpoint for adding the same paabgabe for multiple projektarbeiten + * can be slow for large n since it queries twice per projektarbeit_id + */ + public function postSerientermin() { + $projektarbeit_ids = $_POST['projektarbeit_ids']; + $datum = $_POST['datum']; + $paabgabetyp_kurzbz = $_POST['paabgabetyp_kurzbz']; + $bezeichnung = $_POST['bezeichnung']; + $kurzbz = $_POST['kurzbz']; + + if (!isset($projektarbeit_ids) || !is_array($projektarbeit_ids) || empty($projektarbeit_ids) + || !isset($datum) || isEmptyString($datum) + || !isset($kurzbz) || isEmptyString($kurzbz) + || !isset($bezeichnung) || isEmptyString($bezeichnung) + || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + // old script checks if there already are tbl_paabgabe entries with exact date, type & kurzbz + // for each termin - good to check that in principle but should not matter in this place. if necessary + // duplicate abgabetermine can be easily deleted manually, also via cronjob@night. + + // since this entry includes the kurzbz string match, it should have only ever mattered when there were + // multiple users entering the exact same set of (date, type, kurzbz) - which is a much more narrow case than the + // general "saveMultiple" function should handle + + // old script afterwards again queries if user is not the zweitbetreuer of any id - this is blocked in the ui + // and should never unintentionally happen + + // TODO: check berechtigung &/|| zuordnung? + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $res = []; + foreach ($projektarbeit_ids as $projektarbeit_id) { + + $result = $this->PaabgabeModel->insert( + array( + 'projektarbeit_id' => $projektarbeit_id, + 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, + 'fixtermin' => false, + 'datum' => $datum, + 'kurzbz' => $kurzbz, + 'insertvon' => getAuthUID(), + 'insertamum' => date('Y-m-d H:i:s') + ) + ); + + $data = $this->getDataOrTerminateWithError($result); + +// $res[] = $data; + + // send mail to student + $result = $this->ProjektarbeitModel->getStudentInfoForProjektarbeitId($projektarbeit_id); + $data = $this->getDataOrTerminateWithError($result); + +// $this->addMeta('emaildata'.$projektarbeit_id, $data); + + $datetime = new DateTime($datum); + $dateEmailFormatted = $datetime->format('d.m.Y'); + + $anredeFillString = $data[0]->anrede=="Herr"?"r":""; + + $fullFormattedNameString = trim($data[0]->titelpre." ".$data[0]->vorname." ".$data[0]->nachname." ".$data[0]->titelpost); + $res[] = $fullFormattedNameString; + + // Prepare mail content + $body_fields = array( + 'anrede' => $data[0]->anrede, + 'anredeFillString' => $anredeFillString, + 'datum' => $dateEmailFormatted, + 'bezeichnung' => $bezeichnung, + 'fullFormattedNameString' => $fullFormattedNameString, + 'kurzbz' => $kurzbz + ); + + $email = $data[0]->uid."@".DOMAIN; + + sendSanchoMail( + 'neuerTerminBachelorMasterbetreuung', + $body_fields, + $email, + $this->p->t('abgabetool', 'neuerTerminBachelorMasterbetreuung') + ); + } + + $this->terminateWithSuccess($res); + + } + + public function fetchDeadlines() { + $person_id = $_POST['person_id']; + + if (!isset($person_id) || isEmptyString($person_id)) + $person_id = getAuthPersonId(); + + + if($person_id !== getAuthPersonId()) { + $this->load->library('PermissionLib'); + $isAdmin = $this->permissionlib->isBerechtigt('admin'); + if(!$isAdmin) $this->terminateWithError($this->p->t('ui', 'keineBerechtigung'), 'general'); + } + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $result = $this->PaabgabeModel->getDeadlines($person_id); + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } } diff --git a/application/models/education/Paabgabe_model.php b/application/models/education/Paabgabe_model.php index 558059f72..343a86706 100644 --- a/application/models/education/Paabgabe_model.php +++ b/application/models/education/Paabgabe_model.php @@ -30,5 +30,35 @@ class Paabgabe_model extends DB_Model return $this->execQuery($qry, array($projektarbeit_id)); } + + /** + * Gets all Paabgabe Termin Deadlines of zugewiesene Projektarbeiten as a Mitarbeiter for Terminübersicht Abgabetool. + * @param int $person_id + * @return object + */ + public function getDeadlines($person_id) + { + $qry = "SELECT + DISTINCT TO_CHAR(tbl_paabgabe.datum, 'DD.MM.YYYY') as datum, tbl_paabgabe.fixtermin, tbl_paabgabe.kurzbz, + person_student.vorname as stud_vorname, person_student.nachname as stud_nachname, + person_student.titelpre as stud_titelpre, person_student.titelpost as stud_titelpost, + tbl_lehrveranstaltung.semester, UPPER(tbl_studiengang.typ || tbl_studiengang.kurzbz) as stg, + tbl_paabgabetyp.bezeichnung as typ_bezeichnung + FROM + campus.tbl_paabgabe + JOIN lehre.tbl_projektarbeit USING(projektarbeit_id) + JOIN lehre.tbl_projektbetreuer USING(projektarbeit_id) + JOIN public.tbl_benutzer bn_student ON(tbl_projektarbeit.student_uid=bn_student.uid) + JOIN public.tbl_person person_student ON(bn_student.person_id=person_student.person_id) + JOIN lehre.tbl_lehreinheit ON(tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung ON(tbl_lehreinheit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id) + JOIN public.tbl_studiengang ON(tbl_lehrveranstaltung.studiengang_kz=tbl_studiengang.studiengang_kz) + JOIN campus.tbl_paabgabetyp USING(paabgabetyp_kurzbz) + WHERE + tbl_projektbetreuer.person_id= ? AND tbl_paabgabe.datum>=now() AND bn_student.aktiv + ORDER BY datum"; + + return $this->execReadOnlyQuery($qry, array($person_id)); + } } diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index 1041b3aec..4083dbf6e 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -212,7 +212,11 @@ class Projektarbeit_model extends DB_Model return $this->execReadOnlyQuery($qry, array($studentUID, $maUID)); } - + + /** + * Get a List of Projektarbeiten of a mitarbeiter with zuordnung + * used by the mitarbeiter cis4 abgabetool. + */ public function getMitarbeiterProjektarbeiten($uid, $showAll){ $qry = "SELECT * @@ -242,4 +246,19 @@ class Projektarbeit_model extends DB_Model return $this->execReadOnlyQuery($qry, array($uid)); } + + /** + * Fetch Student info relevant to a projektarbeit_id + */ + public function getStudentInfoForProjektarbeitId($projektarbeit_id) { + + $qry = "SELECT * + FROM campus.vw_student + WHERE uid IN( + SELECT student_uid + FROM lehre.tbl_projektarbeit + WHERE projektarbeit_id = ? )"; + + return $this->execReadOnlyQuery($qry, array($projektarbeit_id)); + } } diff --git a/public/js/api/lehre.js b/public/js/api/lehre.js index 2bf6dd277..5797a2c75 100644 --- a/public/js/api/lehre.js +++ b/public/js/api/lehre.js @@ -76,6 +76,22 @@ export default { } const url = '/api/frontend/v1/Lehre/deleteProjektarbeitAbgabe'; + return this.$fhcApi.post(url, payload, null) + }, + postSerientermin(datum, paabgabetyp_kurzbz, bezeichnung, kurzbz, projektarbeit_ids) { + const payload = { + datum, paabgabetyp_kurzbz, bezeichnung, kurzbz, projektarbeit_ids + } + const url = '/api/frontend/v1/Lehre/postSerientermin'; + + return this.$fhcApi.post(url, payload, null) + }, + fetchDeadlines(person_id) { + const payload = { + person_id + } + const url = '/api/frontend/v1/Lehre/fetchDeadlines'; + return this.$fhcApi.post(url, payload, null) } } \ No newline at end of file diff --git a/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js index b04db0a83..5e6b006b9 100644 --- a/public/js/apps/Dashboard/Fhc.js +++ b/public/js/apps/Dashboard/Fhc.js @@ -12,6 +12,7 @@ import Info from "../../components/Cis/Mylv/Semester/Studiengang/Lv/Info.js"; import RoomInformation, {DEFAULT_MODE_RAUMINFO} from "../../components/Cis/Mylv/RoomInformation.js"; import AbgabetoolStudent from "../../components/Cis/Abgabetool/AbgabetoolStudent.js"; import AbgabetoolMitarbeiter from "../../components/Cis/Abgabetool/AbgabetoolMitarbeiter.js"; +import DeadlineOverview from "../../components/Cis/Abgabetool/DeadlineOverview.js"; @@ -44,6 +45,12 @@ const router = VueRouter.createRouter({ component: AbgabetoolMitarbeiter, props: true }, + { + path: `/Cis/Abgabetool/Deadlines/:person_uid_prop?`, + name: 'DeadlineOverview', + component: DeadlineOverview, + props: true + }, { path: `/Cis/Raumsuche`, name: 'Raumsuche', diff --git a/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js index 7e0da66f6..c49dcfd0a 100644 --- a/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js +++ b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js @@ -19,6 +19,7 @@ export const AbgabeMitarbeiterDetail = { }, data() { return { + oldPaBeurteilungLink: 'https://moodle.technikum-wien.at/mod/page/view.php?id=1005052', // TODO: inject from app & app provide link from config eidAkzeptiert: false, enduploadTermin: null, allActiveLanguages: FHC_JS_DATA_STORAGE_OBJECT.server_languages, @@ -44,16 +45,7 @@ export const AbgabeMitarbeiterDetail = { paabgabetyp_kurzbz: 'enda', bezeichnung: 'Endabgabe im Sekretariat' } - ], - form: Vue.reactive({ - sprache: '', - abstract: '', - abstract_en: '', - schlagwoerter: '', - schlagwoerter_en: '', - kontrollschlagwoerter: '', - seitenanzahl: 1, - }) + ] } }, methods: { @@ -171,21 +163,14 @@ export const AbgabeMitarbeiterDetail = { window.open(link, '_blank') }, openPlagiatcheck() { - // todo: hardcoded turnitin link pfui? + // todo: hardcoded turnitin link? const link = "https://technikum-wien.turnitin.com/sso/sp/redwood/saml/5IyfmBr2OcSIaWQTKlFCGj/start" window.open(link, '_blank') - } - }, - watch: { - projektarbeit(newVal) { - // default select german if projektarbeit sprache was null - this.form.sprache = newVal.sprache ? this.allActiveLanguages.find(lang => lang.sprache == newVal.sprache) : this.allActiveLanguages.find(lang => lang.sprache == 'German') - this.form.abstract = newVal.abstract - this.form.abstract_en = newVal.abstract_en - this.form.schlagwoerter = newVal.schlagwoerter - this.form.schlagwoerter_en = newVal.schlagwoerter_en - this.form.kontrollschlagwoerter = newVal.kontrollschlagwoerter - this.form.seitenanzahl = newVal.seitenanzahl + }, + openBenotung() { + const path = this.projektarbeit?.betreuerart_kurzbz == 'Zweitbegutachter' ? 'ProjektarbeitsbeurteilungZweitbegutachter' : 'ProjektarbeitsbeurteilungErstbegutachter' + const link = FHC_JS_DATA_STORAGE_OBJECT.app_root + 'index.ci.php/extensions/FHC-Core-Projektarbeitsbeurteilung/' + path + window.open(link, '_blank') } }, computed: { @@ -212,28 +197,47 @@ export const AbgabeMitarbeiterDetail = { template: `
+
{{$p.t('abgabetool/c4abgabeMitarbeiterbereich')}}
+ +

{{projektarbeit?.student}}

{{projektarbeit?.titel}}

{{projektarbeit?.zweitbegutachter}}

-
-
- +
+
+
+ +
+
+ + Kein Endupload vorhanden! +
+
+
+
+ +
+ +
+
+
+ +
+
- -
@@ -303,101 +307,6 @@ export const AbgabeMitarbeiterDetail = {
- - - - - `, }; diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js b/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js index 06a1f2d00..2d2316036 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js @@ -1,13 +1,18 @@ import {CoreFilterCmpt} from "../../../components/filter/Filter.js"; import AbgabeDetail from "./AbgabeMitarbeiterDetail.js"; import VerticalSplit from "../../verticalsplit/verticalsplit.js" +import BsModal from '../../Bootstrap/Modal.js'; export const AbgabetoolMitarbeiter = { name: "AbgabetoolMitarbeiter", components: { + BsModal, CoreFilterCmpt, AbgabeDetail, VerticalSplit, + Dropdown: primevue.dropdown, + Textarea: primevue.textarea, + VueDatePicker }, props: { viewData: { @@ -21,6 +26,39 @@ export const AbgabetoolMitarbeiter = { }, data() { return { + saving: false, + loading: false, + // TODO: fetch types + allAbgabeTypes: [ + { + paabgabetyp_kurzbz: 'abstract', + bezeichnung: 'Entwurf' + }, + { + paabgabetyp_kurzbz: 'zwischen', + bezeichnung: 'Zwischenabgabe' + }, + { + paabgabetyp_kurzbz: 'note', + bezeichnung: 'Benotung' + }, + { + paabgabetyp_kurzbz: 'end', + bezeichnung: 'Endupload' + }, + { + paabgabetyp_kurzbz: 'enda', + bezeichnung: 'Endabgabe im Sekretariat' + } + ], + serienTermin: Vue.reactive({ + datum: new Date(), + bezeichnung: { + paabgabetyp_kurzbz: 'zwischen', + bezeichnung: 'Zwischenabgabe' + }, + kurzbz: '' + }), showAll: false, tabulatorUuid: Vue.ref(0), selectedData: [], @@ -38,6 +76,7 @@ export const AbgabetoolMitarbeiter = { layout: 'fitDataStretch', placeholder: this.$p.t('global/noDataAvailable'), selectable: true, + selectableCheck: this.selectionCheck, columns: [ { formatter: 'rowSelection', @@ -59,7 +98,7 @@ export const AbgabetoolMitarbeiter = { {title: Vue.computed(() => this.$p.t('abgabetool/c4stg')), field: 'stg', formatter: this.centeredTextFormatter, widthGrow: 2}, {title: Vue.computed(() => this.$p.t('abgabetool/c4sem')), field: 'studiensemester_kurzbz', formatter: this.centeredTextFormatter, widthGrow: 1}, {title: Vue.computed(() => this.$p.t('abgabetool/c4titel')), field: 'titel', formatter: this.centeredTextFormatter, maxWidth: 500, widthGrow: 8}, - {title: Vue.computed(() => this.$p.t('abgabetool/c4beteuerart')), field: 'betreuerart_beschreibung',formatter: this.centeredTextFormatter, widthGrow: 8} + {title: Vue.computed(() => this.$p.t('abgabetool/c4betreuerart')), field: 'betreuerart_beschreibung',formatter: this.centeredTextFormatter, widthGrow: 8} ], persistence: false, }, @@ -74,24 +113,10 @@ export const AbgabetoolMitarbeiter = { handler: async (e, cell) => { if(cell.getColumn().getField() === "details") { this.setDetailComponent(cell.getValue()) + this.undoSelection(cell) + } else if (cell.getColumn().getField() === "mail") { + this.undoSelection(cell) } - e.stopPropagation() - - } - }, - { - event: "rowClick", - handler: async (e, row) => { - - e.stopPropagation() - - } - }, - { - event: "rowSelected", - handler: async (row) => { - - } }, { @@ -103,16 +128,82 @@ export const AbgabetoolMitarbeiter = { ]}; }, methods: { + getOptionLabelAbgabetyp(option){ + return option.bezeichnung + }, + formatDate(dateParam) { + const date = new Date(dateParam) + // handle missing leading 0 + const padZero = (num) => String(num).padStart(2, '0'); + + const month = padZero(date.getMonth() + 1); // Months are zero-based + const day = padZero(date.getDate()); + const year = date.getFullYear(); + + return `${day}.${month}.${year}`; + }, + undoSelection(cell) { + // checks if cells row is selected and unselects -> imitates columns which dont trigger row selection + // but actually just revert it after the fact + + const row = cell.getRow() + if(row.isSelected()) { + row.deselect(); + } + }, + selectionCheck(row) { + const data = row.getData() + if(data?.betreuerart_kurzbz == 'Zweitbegutachter') return false + return true + }, showDeadlines(){ - // TODO: open seperate view in new window containing all future deadlines for the employee + const link = FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + + '/Cis/Abgabetool/Deadlines' + window.open(link, '_blank') }, toggleShowAll(showall) { this.showAll = showall - // TODO: debug tabulator row render - this.loadProjektarbeiten(showall, () => { this.$refs.abgabeTable?.tabulator.redraw(true) }) + this.loading = true + this.loadProjektarbeiten(showall, () => { + this.$refs.abgabeTable?.tabulator.redraw(true) + this.$refs.abgabeTable?.tabulator.setSort([]); + this.loading = false + }) + }, + openAddSeriesModal() { + this.$refs.modalContainerAddSeries.show() }, addSeries() { + this.saving = true + this.$fhcApi.factory.lehre.postSerientermin( + this.serienTermin.datum.toISOString(), + this.serienTermin.bezeichnung.paabgabetyp_kurzbz, + this.serienTermin.bezeichnung.bezeichnung, + this.serienTermin.kurzbz, + this.selectedData?.map(projekt => projekt.projektarbeit_id) + ).then(res => { + if (res.meta.status === "success" && res.data) { + this.$fhcAlert.alertSuccess(this.$p.t('abgabetool/serienTerminGespeichert')) + // TODO: sticky lifetime erhöhen um sinnvoll lesen zu können? + this.$fhcAlert.alertInfo(this.$p.t('abgabetool/serienTerminEmailSentInfo', [this.createInfoString(res.data)])); + } else { + this.$fhcAlert.alertError(this.$p.t('abgabetool/errorSerienterminSpeichern')) + } + }).finally(()=>{ + this.saving = false + }) + + this.$refs.modalContainerAddSeries.hide() + }, + createInfoString(data) { + let str = ''; + data.forEach(name => { + str += name + str += '; ' + }) + + return str }, isPastDate(date) { return new Date(date) < new Date(Date.now()) @@ -283,8 +374,57 @@ export const AbgabetoolMitarbeiter = { this.setupMounted() }, template: ` - - + + + + + @@ -296,9 +436,9 @@ export const AbgabetoolMitarbeiter = { @uuidDefined="handleUuidDefined" ref="abgabeTable" :newBtnShow="true" - :newBtnLabel="$p.t('global/neueTerminserie')" + :newBtnLabel="$p.t('abgabetool/neueTerminserie')" :newBtnDisabled="!selectedData.length" - @click:new=addSeries + @click:new=openAddSeriesModal :tabulator-options="abgabeTableOptions" :tabulator-events="abgabeTableEventHandlers" tableOnly @@ -316,6 +456,14 @@ export const AbgabetoolMitarbeiter = { {{ $p.t('abgabetool/showDeadlines') }} + +
+ {{ $p.t('abgabetool/currentlySaving') }} +
+
+ {{ $p.t('abgabetool/currentlyLoading') }} +
+ diff --git a/public/js/components/Cis/Abgabetool/DeadlineOverview.js b/public/js/components/Cis/Abgabetool/DeadlineOverview.js new file mode 100644 index 000000000..d2b133979 --- /dev/null +++ b/public/js/components/Cis/Abgabetool/DeadlineOverview.js @@ -0,0 +1,151 @@ +import {CoreFilterCmpt} from "../../../components/filter/Filter.js"; + +export const DeadlineOverview = { + name: "DeadlineOverview", + components: { + CoreFilterCmpt, + }, + props: { + person_uid_prop: { + default: null + }, + viewData: { + type: Object, + required: true, + default: () => ({name: '', uid: ''}), + validator(value) { + return value && value.name && value.uid + } + } + }, + data() { + return { + fullName: null, // TODO: fetch this somewhere + deadlines: null, + tabulatorUuid: Vue.ref(0), + tableBuiltResolve: null, + tableBuiltPromise: null, + deadlineTableOptions: { + height: 700, + index: 'projektarbeit_id', + layout: 'fitColumns', + placeholder: this.$p.t('global/noDataAvailable'), + columns: [ + {title: Vue.computed(() => this.$p.t('abgabetool/c4zieldatum')), field: 'datum', formatter: this.centeredTextFormatter, widthGrow: 1, tooltip: false}, + {title: Vue.computed(() => this.$p.t('abgabetool/c4fixtermin')), field: 'fixterminstring', formatter: this.centeredTextFormatter, widthGrow: 1, tooltip: false}, + {title: Vue.computed(() => this.$p.t('abgabetool/c4abgabetyp')), field: 'typ_bezeichnung', formatter: this.centeredTextFormatter, widthGrow: 1}, + {title: Vue.computed(() => this.$p.t('abgabetool/c4abgabekurzbz')), field: 'kurzbz', formatter: this.centeredTextFormatter, widthGrow: 3}, + {title: Vue.computed(() => this.$p.t('person/studentIn')), field: 'student', formatter: this.centeredTextFormatter, widthGrow: 2}, + {title: Vue.computed(() => this.$p.t('abgabetool/c4stg')), field: 'stg', formatter: this.centeredTextFormatter,widthGrow: 1}, + {title: Vue.computed(() => this.$p.t('abgabetool/c4sem')), field: 'semester', formatter: this.centeredTextFormatter, widthGrow: 1} + ], + persistence: false, + }, + deadlineTableEventHandlers: [{ + event: "tableBuilt", + handler: async () => { + this.tableBuiltResolve() + } + }, + { + event: "cellClick", + handler: async (e, cell) => { + + if(cell.getColumn().getField() === "details") { + const val = cell.getValue() + + if(val.mode === 'detailTermine') { + this.setDetailComponent(cell.getValue()) + } else if (val.mode === 'beurteilungDownload') { + const pdfExportLink = FHC_JS_DATA_STORAGE_OBJECT.app_root + 'cis/private/pdfExport.php?xml=projektarbeitsbeurteilung.xml.php&xsl=Projektbeurteilung&betreuerart_kurzbz='+val.betreuerart_kurzbz+'&projektarbeit_id='+val.projektarbeit_id+'&person_id=' + val.betreuer_person_id + // const pdfExportLink2 = FHC_JS_DATA_STORAGE_OBJECT.app_root + 'cis/private/lehre/projektbeurteilungDocumentExport.php?betreuerart_kurzbz='+val.betreuerart_kurzbz+'&projektarbeit_id='+val.projektarbeit_id+'&person_id=' + val.betreuer_person_id + window.open(pdfExportLink, '_blank') + } + + } else if (cell.getColumn().getField() === "beurteilung") { + const val = cell.getValue() + + if(val != '-') window.open(val, '_blank') + } + e.stopPropagation() + + } + } + ]}; + }, + methods: { + centeredTextFormatter(cell) { + const val = cell.getValue() + + return '
' + + '

'+val+'

' + }, + tableResolve(resolve) { + this.tableBuiltResolve = resolve + }, + loadDeadlines() { + this.$fhcApi.factory.lehre.fetchDeadlines(this.person_uid_prop ?? null) + .then(res => { + if(res?.data) this.setupData(res.data) + }) + }, + setupData(data) { + this.deadlines = data + + this.deadlines.forEach(dl => { + dl.student = (dl.stud_titelpre ? (dl.stud_titelpre + ' ') :'') + dl.stud_vorname + ' ' + dl.stud_nachname + (dl.stud_titelpost ? (' ' + dl.stud_titelpost) :'') + dl.fixterminstring = dl.fixtermin ? this.$p.t('abgabetool/c4yes') : this.$p.t('abgabetool/c4no') + }) + + this.$refs.deadlineTable.tabulator.setColumns(this.deadlineTableOptions.columns) + this.$refs.deadlineTable.tabulator.setData(this.deadlines); + }, + handleUuidDefined(uuid) { + this.tabulatorUuid = uuid + }, + calcMaxTableHeight() { + const tableID = this.tabulatorUuid ? ('-' + this.tabulatorUuid) : '' + const tableDataSet = document.getElementById('filterTableDataset' + tableID); + if(!tableDataSet) return + const rect = tableDataSet.getBoundingClientRect(); + + this.deadlineTableOptions.height = window.visualViewport.height - rect.top + this.$refs.deadlineTable.tabulator.setHeight(this.deadlineTableOptions.height) + }, + async setupMounted() { + this.tableBuiltPromise = new Promise(this.tableResolve) + await this.tableBuiltPromise + + this.loadDeadlines() + this.calcMaxTableHeight() + } + }, + watch: { + + }, + computed: { + + }, + created() { + + }, + mounted() { + this.setupMounted() + }, + template: ` +

{{$p.t('abgabetool/deadlinesTitle')}} {{ fullName ? ('-' + fullName) : ''}}

+
+ + + `, +}; + +export default DeadlineOverview; diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index ae1c9daaa..9e9385c5c 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -30938,7 +30938,7 @@ array( ), array( 'sprache' => 'English', - 'text' => 'Wrong parameters tranferred', + 'text' => 'Wrong parameters transferred', 'description' => '', 'insertvon' => 'system' ) @@ -37879,6 +37879,66 @@ array( ) ) ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'neuerTerminBachelorMasterbetreuung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Neuer Termin Bachelor-/Masterarbeitsbetreuung", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "New date for Bachelor/Master thesis supervision", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'neueTerminserie', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Terminserie anlegen", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Create recurring deadline", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'serienTerminEmailSentInfo', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Email über neuen Abgabetermin versendet an: {0}", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Email about new deadline sent to: {0}", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'abgabetool', @@ -39784,6 +39844,26 @@ array( ) ) ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4aeltereParbeitBenoten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Projektarbeit für älteres Semester, bitte Word-Formular zur Benotung verwenden!', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Thesis handed in for older semester, please use word form for assessment!', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'abgabetool', @@ -39964,6 +40044,66 @@ array( ) ) ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'deadlinesTitle', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Terminübersicht", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Deadline Overview", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4yes', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Ja", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Yes", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4no', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Nein", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "No", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'abgabetool', @@ -40044,6 +40184,46 @@ array( ) ) ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'currentlySaving', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Speichern... ", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Saving... ', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'currentlyLoading', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Laden... ", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Loading... ', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'abgabetool',