diff --git a/application/config/routes.php b/application/config/routes.php index 9a3651f24..11315f47d 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -65,6 +65,7 @@ $route['Cis/LvPlan/.*'] = 'Cis/LvPlan/index/$1'; $route['Cis/MyLvPlan/.*'] = 'Cis/MyLvPlan/index/$1'; $route['Cis/MyLv/.*'] = 'Cis/MyLv/index/$1'; +$route['Abgabetool/Assistenz'] = 'Cis/Abgabetool/Assistenz'; $route['Abgabetool/Mitarbeiter'] = 'Cis/Abgabetool/Mitarbeiter'; $route['Abgabetool/Student'] = 'Cis/Abgabetool/Student'; $route['Abgabetool/Student/.*'] = 'Cis/Abgabetool/Student/$1'; diff --git a/application/controllers/Cis/Abgabetool.php b/application/controllers/Cis/Abgabetool.php index 35970b6e9..223af86f5 100644 --- a/application/controllers/Cis/Abgabetool.php +++ b/application/controllers/Cis/Abgabetool.php @@ -15,9 +15,10 @@ class Abgabetool extends Auth_Controller parent::__construct([ 'index' => self::PERM_LOGGED, 'getStudentProjektarbeitAbgabeFile' => array('basis/abgabe_student:rw', 'basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw'), - 'Mitarbeiter' => self::PERM_LOGGED, - 'Student' => self::PERM_LOGGED, - 'Deadlines' => self::PERM_LOGGED + 'Mitarbeiter' => array('basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw'), + 'Assistenz' => array('basis/abgabe_assistenz:rw'), + 'Student' => array('basis/abgabe_student:rw', 'basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw'), + 'Deadlines' => array('basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw') ]); } @@ -29,6 +30,7 @@ class Abgabetool extends Auth_Controller */ public function index() { + // TODO: do we even need this? $viewData = array( 'uid'=>getAuthUID(), @@ -71,6 +73,20 @@ class Abgabetool extends Auth_Controller } } + public function Assistenz() + { + + $viewData = array( + 'uid'=>getAuthUID(), + ); + + if(defined('CIS4') && CIS4) { + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'AbgabetoolAssistenz']); + } else { + $this->load->view('Cis/Abgabetool.php', ['uid' => getAuthUID(), 'route' => 'AbgabetoolAssistenz']); + } + } + public function Deadlines() { diff --git a/application/controllers/api/frontend/v1/Abgabe.php b/application/controllers/api/frontend/v1/Abgabe.php index 8586c99bc..4a9706789 100644 --- a/application/controllers/api/frontend/v1/Abgabe.php +++ b/application/controllers/api/frontend/v1/Abgabe.php @@ -38,7 +38,8 @@ class Abgabe extends FHCAPI_Controller 'postSerientermin' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_lektor:rw'), 'fetchDeadlines' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_lektor:rw'), 'getPaAbgabetypen' => self::PERM_LOGGED, - 'getNoten' => self::PERM_LOGGED + 'getNoten' => self::PERM_LOGGED, + 'getProjektarbeitenForStudiengang' =>array('basis/abgabe_assistenz:rw') ]); $this->load->library('PhrasesLib'); @@ -148,6 +149,9 @@ class Abgabe extends FHCAPI_Controller $pa->email = $data[0]->private_email; } if($pa->zweitbetreuer_person_id !== null) { + + // TODO: dont have to wait for 2038, see assistenz query in projektarbeit_model + // zweitbetreuer info since the 'getStudentProjektarbeitenWithBetreuer' query got quiete large, // enjoy optimizing that one in 2038. we need this to render a string like // Zweitbegutachter: FH-Prof. PD DI Dr. techn. Vorname Nachname MBA @@ -850,4 +854,41 @@ class Abgabe extends FHCAPI_Controller $subject ); } + + public function getProjektarbeitenForStudiengang() { + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $studiengang_kz = $this->input->get("studiengang_kz",TRUE); + + if (!isset($studiengang_kz) || isEmptyString($studiengang_kz)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + // TODO revert arr return new/old +// $arr = $this->ProjektarbeitModel->getProjektarbeitenForStudiengang($studiengang_kz); +// $result = $arr[0]; + $result = $this->ProjektarbeitModel->getProjektarbeitenForStudiengang($studiengang_kz); + $projektarbeiten = $this->getDataOrTerminateWithError($result); + + $mapFunc = function($projektarbeit) { + return $projektarbeit->projektarbeit_id; + }; + $projektarbeiten_ids = array_map($mapFunc, $projektarbeiten); + + $ret = $this->ProjektarbeitModel->getProjektarbeitenAbgabetermine($projektarbeiten_ids); + $projektabgaben = $this->getDataOrTerminateWithError($ret); + + // map the abgaben into projektarbeiten + + foreach($projektarbeiten as $projektarbeit) { + $filterFunc = function($projektabgabe) use ($projektarbeit) { + return $projektabgabe->projektarbeit_id == $projektarbeit->projektarbeit_id; + }; + + + $projektarbeit->abgabetermine = array_values(array_filter($projektabgaben, $filterFunc)); + + } + + $this->terminateWithSuccess(array($projektarbeiten, DOMAIN)); + } } \ No newline at end of file diff --git a/application/models/education/Paabgabetyp_model.php b/application/models/education/Paabgabetyp_model.php index fce46b3a0..034daca44 100644 --- a/application/models/education/Paabgabetyp_model.php +++ b/application/models/education/Paabgabetyp_model.php @@ -13,7 +13,7 @@ class Paabgabetyp_model extends DB_Model } public function getAll() { - $qry = "SELECT * FROM campus.tbl_paabgabetyp"; + $qry = "SELECT * FROM campus.tbl_paabgabetyp ORDER BY bezeichnung"; return $this->execReadOnlyQuery($qry); } diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index 76908600c..821a8d007 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -183,12 +183,32 @@ class Projektarbeit_model extends DB_Model return $this->execReadOnlyQuery($qry, array($projektarbeit_id)); } + public function getProjektarbeitenAbgabetermine($projektarbeiten_ids) { + $qry ="SELECT campus.tbl_paabgabe.paabgabe_id, + campus.tbl_paabgabe.projektarbeit_id, + campus.tbl_paabgabe.fixtermin, + campus.tbl_paabgabe.kurzbz, + campus.tbl_paabgabe.datum, + campus.tbl_paabgabe.note, + campus.tbl_paabgabe.upload_allowed, + campus.tbl_paabgabe.beurteilungsnotiz, + campus.tbl_paabgabetyp.paabgabetyp_kurzbz, + campus.tbl_paabgabetyp.bezeichnung, + campus.tbl_paabgabe.abgabedatum, + campus.tbl_paabgabe.insertvon + FROM campus.tbl_paabgabe JOIN campus.tbl_paabgabetyp USING(paabgabetyp_kurzbz) + WHERE campus.tbl_paabgabe.projektarbeit_id IN ? + ORDER BY campus.tbl_paabgabe.datum"; + + return $this->execReadOnlyQuery($qry, array($projektarbeiten_ids)); + } + public function getProjektbetreuerAnrede($bperson_id) { - $qry_betr="SELECT distinct trim(COALESCE(titelpre,'')||' '||COALESCE(vorname,'')||' '||COALESCE(nachname,'')||' '||COALESCE(titelpost,'')) as first, + $qry_betr="SELECT DISTINCT trim(COALESCE(titelpre,'')||' '||COALESCE(vorname,'')||' '||COALESCE(nachname,'')||' '||COALESCE(titelpost,'')) as first, public.tbl_mitarbeiter.mitarbeiter_uid, anrede FROM public.tbl_person JOIN lehre.tbl_projektbetreuer ON(lehre.tbl_projektbetreuer.person_id=public.tbl_person.person_id) - JOIN public.tbl_benutzer ON(public.tbl_benutzer.person_id=public.tbl_person.person_id) - JOIN public.tbl_mitarbeiter ON(public.tbl_benutzer.uid=public.tbl_mitarbeiter.mitarbeiter_uid) + LEFT JOIN public.tbl_benutzer ON(public.tbl_benutzer.person_id=public.tbl_person.person_id) + LEFT JOIN public.tbl_mitarbeiter ON(public.tbl_benutzer.uid=public.tbl_mitarbeiter.mitarbeiter_uid) WHERE public.tbl_person.person_id= ?"; return $this->execReadOnlyQuery($qry_betr, [$bperson_id]); @@ -298,6 +318,128 @@ class Projektarbeit_model extends DB_Model // paarbeit sollte nur ab einem Studiensemester online bewertet werden return $version === null ? null : $version->isCurrent; } + + public function getProjektarbeitenForStudiengang($studiengang_kz) { + + // TODO: select less fields, a lot of useless data over here + + $old_qry = "SELECT *, + (SELECT orgform_kurzbz + FROM tbl_prestudentstatus + WHERE prestudent_id=(Select prestudent_id from tbl_student where student_uid=xy.uid limit 1) + ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1 + ) as organisationsform + FROM (SELECT DISTINCT ON(tbl_projektarbeit.projektarbeit_id) public.tbl_studiengang.bezeichnung as stgbez,tbl_projekttyp.bezeichnung AS prjbez,* FROM lehre.tbl_projektarbeit + LEFT JOIN public.tbl_benutzer on(uid=student_uid) + LEFT JOIN public.tbl_person on(tbl_benutzer.person_id=tbl_person.person_id) + LEFT JOIN lehre.tbl_lehreinheit using(lehreinheit_id) + LEFT JOIN lehre.tbl_lehrveranstaltung using(lehrveranstaltung_id) + LEFT JOIN public.tbl_studiengang using(studiengang_kz) + LEFT JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz) + WHERE (projekttyp_kurzbz='Bachelor' OR projekttyp_kurzbz='Diplom') + AND public.tbl_benutzer.aktiv + AND lehre.tbl_projektarbeit.note IS NULL + AND public.tbl_studiengang.studiengang_kz = ? + ORDER BY tbl_projektarbeit.projektarbeit_id desc) as xy + ORDER BY nachname"; + + + $new_qry = " + SELECT + DISTINCT ON(tbl_projektarbeit.projektarbeit_id) + tbl_projektarbeit.projekttyp_kurzbz, + tbl_projektarbeit.titel, + tbl_projektarbeit.projektarbeit_id, + tbl_studiengang.typ, tbl_studiengang.kurzbz, + student_benutzer.uid as student_uid, + student_person.vorname as student_vorname, + student_person.nachname as student_nachname, + tbl_student.matrikelnr, tbl_lehreinheit.studiensemester_kurzbz, + betreuer_benutzer.uid as betreuer_benutzer_uid, + betreuer_person.vorname as betreuer_vorname, + betreuer_person.nachname as betreuer_nachname, + lehre.tbl_projektbetreuer.betreuerart_kurzbz as betreuerart, + lehre.tbl_projektbetreuer.person_id as betreuer_person_id, + lehre.tbl_projektarbeit.sprache as sprache, + lehre.tbl_projektarbeit.seitenanzahl as seitenanzahl, + lehre.tbl_projektarbeit.kontrollschlagwoerter as kontrollschlagwoerter, + lehre.tbl_projektarbeit.schlagwoerter as schlagwoerter, + lehre.tbl_projektarbeit.schlagwoerter_en as schlagwoerter_en, + lehre.tbl_projektarbeit.abstract as abstract, + lehre.tbl_projektarbeit.abstract_en as abstract_en, + lehre.tbl_projektarbeit.insertamum as insertamum, + ( + SELECT orgform_kurzbz + FROM tbl_prestudentstatus + WHERE prestudent_id = (SELECT prestudent_id + FROM tbl_student + WHERE student_uid = student_benutzer.uid + LIMIT 1) + ORDER BY datum DESC, insertamum DESC, ext_id DESC + LIMIT 1 + ) + as organisationsform, + ( + SELECT person_id + FROM lehre.tbl_projektbetreuer + WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter') + LIMIT 1 + ) + AS zweitbetreuer_person_id, + ( + SELECT betreuerart_kurzbz + FROM lehre.tbl_projektbetreuer + WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter') + LIMIT 1 + ) + AS zweitbetreuer_betreuerart_kurzbz, + ( + SELECT tbl_betreuerart.beschreibung + FROM lehre.tbl_projektbetreuer + JOIN lehre.tbl_betreuerart USING (betreuerart_kurzbz) + WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter', 'Senatsmitglied') + LIMIT 1 + ) + AS zweitbetreuer_betreuerart_beschreibung, + ( + SELECT trim(COALESCE(titelpre, '') || ' ' || COALESCE(vorname, '') || ' ' || COALESCE(nachname, '') || ' ' || + COALESCE(titelpost, '')) + FROM public.tbl_person + JOIN lehre.tbl_projektbetreuer ON (lehre.tbl_projektbetreuer.person_id = public.tbl_person.person_id) + LEFT JOIN public.tbl_benutzer ON (public.tbl_benutzer.person_id = public.tbl_person.person_id) + LEFT JOIN public.tbl_mitarbeiter ON (public.tbl_benutzer.uid = public.tbl_mitarbeiter.mitarbeiter_uid) + WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter') + LIMIT 1 + ) + as zweitbetreuer_full_name + FROM lehre.tbl_projektarbeit + LEFT JOIN public.tbl_benutzer student_benutzer ON (student_benutzer.uid = lehre.tbl_projektarbeit.student_uid) + LEFT JOIN public.tbl_person student_person ON (student_benutzer.person_id = student_person.person_id) + LEFT JOIN public.tbl_student on(student_benutzer.uid = public.tbl_student.student_uid) + LEFT JOIN lehre.tbl_lehreinheit USING (lehreinheit_id) + LEFT JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id) + LEFT JOIN public.tbl_studiengang ON (public.tbl_student.studiengang_kz = public.tbl_studiengang.studiengang_kz) + LEFT JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz) + LEFT JOIN lehre.tbl_projektbetreuer USING (projektarbeit_id) + LEFT JOIN public.tbl_person betreuer_person ON (betreuer_person.person_id = lehre.tbl_projektbetreuer.person_id) + LEFT JOIN public.tbl_benutzer betreuer_benutzer ON (betreuer_person.person_id = betreuer_benutzer.person_id) + WHERE (projekttyp_kurzbz = 'Bachelor' OR projekttyp_kurzbz = 'Diplom') + AND student_benutzer.aktiv AND (lehre.tbl_projektbetreuer.betreuerart_kurzbz = 'Erstbegutachter' OR lehre.tbl_projektbetreuer.betreuerart_kurzbz = 'Begutachter') + -- AND lehre.tbl_projektarbeit.note IS NULL + -- AND public.tbl_studiengang.studiengang_kz= 257 + AND public.tbl_studiengang.studiengang_kz = ? + ORDER BY tbl_projektarbeit.projektarbeit_id DESC, student_person.nachname ASC + "; +// $oldres = $this->execReadOnlyQuery($old_qry, array($studiengang_kz)); +// $newres = $this->execReadOnlyQuery($new_qry, array($studiengang_kz)); +// return array($newres, $oldres); + + return $this->execReadOnlyQuery($new_qry, array($studiengang_kz)); + } /** * Holt sich Version der Projektarbeit. diff --git a/application/views/Cis/Abgabetool.php b/application/views/Cis/Abgabetool.php index 1b1994e0a..af259ca48 100644 --- a/application/views/Cis/Abgabetool.php +++ b/application/views/Cis/Abgabetool.php @@ -24,6 +24,7 @@ $includesArray = array( 'vendor/npm-asset/primevue/inputnumber/inputnumber.min.js', 'vendor/npm-asset/primevue/speeddial/speeddial.min.js', 'vendor/npm-asset/primevue/textarea/textarea.min.js', + 'vendor/moment/luxonjs/luxon.min.js' ), 'customJSModules' => array( 'public/js/apps/Abgabetool/Abgabetool.js', diff --git a/public/js/api/factory/abgabe.js b/public/js/api/factory/abgabe.js index c51da95fe..8f4ba61de 100644 --- a/public/js/api/factory/abgabe.js +++ b/public/js/api/factory/abgabe.js @@ -100,4 +100,11 @@ export default { url: '/api/frontend/v1/Abgabe/getNoten' }; }, + getProjektarbeitenForStudiengang(studiengang_kz) { + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getProjektarbeitenForStudiengang', + params: { studiengang_kz } + }; + } }; \ No newline at end of file diff --git a/public/js/apps/Abgabetool/Abgabetool.js b/public/js/apps/Abgabetool/Abgabetool.js index 1336276af..ac73779e8 100644 --- a/public/js/apps/Abgabetool/Abgabetool.js +++ b/public/js/apps/Abgabetool/Abgabetool.js @@ -2,6 +2,7 @@ import PluginsPhrasen from '../../plugins/Phrasen.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"; +import {capitalize} from "../../helpers/StringHelpers.js"; const app = Vue.createApp({ name: 'AbgabetoolApp', @@ -51,6 +52,7 @@ const app = Vue.createApp({ ` }); +app.config.globalProperties.$capitalize = capitalize; app.use(primevue.config.default, { zIndex: { overlay: 9000, diff --git a/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js index 31c59ef36..0a11c4986 100644 --- a/public/js/apps/Dashboard/Fhc.js +++ b/public/js/apps/Dashboard/Fhc.js @@ -14,11 +14,13 @@ 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 AbgabetoolAssistenz from "../../components/Cis/Abgabetool/AbgabetoolAssistenz.js"; import DeadlineOverview from "../../components/Cis/Abgabetool/DeadlineOverview.js"; import Studium from "../../components/Cis/Studium/Studium.js"; import ApiRenderers from '../../api/factory/renderers.js'; import ApiRouteInfo from '../../api/factory/routeinfo.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; @@ -55,6 +57,12 @@ const router = VueRouter.createRouter({ component: AbgabetoolMitarbeiter, props: true }, + { + path: `/Cis/Abgabetool/Assistenz`, + name: 'AbgabetoolAssistenz', + component: AbgabetoolAssistenz, + props: true + }, { path: `/Cis/Abgabetool/Deadlines/:person_uid_prop?`, name: 'DeadlineOverview', @@ -275,6 +283,7 @@ const app = Vue.createApp({ } }, async created(){ + await this.$api .call(ApiRenderers.loadRenderers()) .then(res => res.data) @@ -315,6 +324,7 @@ const app = Vue.createApp({ }, mounted() { document.addEventListener('click', this.handleClick); + }, beforeUnmount() { document.removeEventListener('click', this.handleClick); @@ -323,7 +333,7 @@ const app = Vue.createApp({ // kind of a bandaid for bad css on some pages to avoid horizontal scroll setScrollbarWidth(); - +app.config.globalProperties.$capitalize = capitalize; app.use(router); app.use(primevue.config.default, { zIndex: { diff --git a/public/js/components/Bootstrap/Modal.js b/public/js/components/Bootstrap/Modal.js index a84d9d8d7..15253cfe8 100644 --- a/public/js/components/Bootstrap/Modal.js +++ b/public/js/components/Bootstrap/Modal.js @@ -46,7 +46,8 @@ export default { "hiddenBsModal", "hidePreventedBsModal", "showBsModal", - "shownBsModal" + "shownBsModal", + "toggleFullscreen" ], methods: { dispose() { @@ -66,6 +67,7 @@ export default { }, toggleFullscreen() { this.fullscreen = !this.fullscreen + this.$emit('toggleFullscreen') } }, mounted() { diff --git a/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js index fc804ea3a..fa202a020 100644 --- a/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js +++ b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js @@ -27,12 +27,15 @@ export const AbgabeMitarbeiterDetail = { projektarbeit: { type: Object, default: null + }, + isFullscreen: { + type: Boolean, + default: false } }, data() { return { showAutomagicModalPhrase: false, - sdModel: [], eidAkzeptiert: false, enduploadTermin: null, allActiveLanguages: FHC_JS_DATA_STORAGE_OBJECT.server_languages, @@ -60,8 +63,8 @@ export const AbgabeMitarbeiterDetail = { } }, methods: { - openZusatzdatenModal(termin) { - + getPlaceholderTermin(termin) { + return termin?.bezeichnung?.bezeichnung ?? this.$p.t('abgabetool/abgabetypPlaceholder') }, saveTermin(termin) { const paabgabe_id = termin.paabgabe_id @@ -97,10 +100,10 @@ export const AbgabeMitarbeiterDetail = { // really bad feature imo that will be annoying to deal with // termin is completely new and has negative note - const savedNewWithNegative = !existingTerminRes && !newTerminRes.note?.positiv + const savedNewWithNegative = !existingTerminRes && !newTerminRes.note?.positiv && newTerminRes.note !== null // termin existed previously + oldTermin had different note/positive note or no note at all - const savedExistingNoteAsNegativeAndWasNotNegativeBefore = existingTerminRes && !newTerminRes.note?.positiv && (existingTerminRes.note?.positiv || existingTerminRes.note === undefined) + const savedExistingNoteAsNegativeAndWasNotNegativeBefore = existingTerminRes && !newTerminRes.note?.positiv && newTerminRes.note !== null && (existingTerminRes.note?.positiv || existingTerminRes.note === undefined) const openModalDueToNegativeBeurteilung = savedNewWithNegative || savedExistingNoteAsNegativeAndWasNotNegativeBefore if(openModalDueToNegativeBeurteilung) { @@ -198,6 +201,9 @@ export const AbgabeMitarbeiterDetail = { getOptionLabelAbgabetyp(option){ return option.bezeichnung }, + getOptionDisabled(option) { + return !option.aktiv + }, getNotenOptionLabel(option) { return option.bezeichnung }, @@ -298,8 +304,23 @@ export const AbgabeMitarbeiterDetail = { }, computed: { - activeAbgabeTypeOptions() { - return this.abgabeTypeOptions?.filter(opt => opt.aktiv === true) + getActiveIndexTabArray() { + // here we try to do mind reading logic by assuming which abgabetermine are the most relevant to the current user + + // lets try to take the termin with nearest date and watch who complains and why + let closestIndex = -1; + let minDiff = Infinity; + const today = new Date(); + + this.projektarbeit.abgabetermine.forEach((obj, i) => { + const diff = Math.abs(new Date(obj.datum) - today); + if (diff < minDiff) { + minDiff = diff; + closestIndex = i; + } + }); + + return [closestIndex] }, getEid() { return this.$p.t('abgabetool/c4eidesstattlicheErklaerung') @@ -323,12 +344,16 @@ export const AbgabeMitarbeiterDetail = { }) return qgatefound }, - getPageWrapperStyle() { - return 'position: relative; min-height: 100vh;' - }, getSpeedDialStyle() { return 'position: static !important;' }, + getSpeedDialWrapperStyle() { + // fullscreen -> position wrapper fixed in right bottom corner of viewport/screen + if(this.isFullscreen) return 'position: fixed; z-index: 9999; bottom: 24px; right: 24px;' + + // non fullscreen -> wrapper is positioned on right bottom corner of modal, wherever that is + return 'position: absolute; z-index: 9999; bottom: -28px; right: -28px;' + }, getTooltipVerspaetet() { return { value: this.$p.t('abgabetool/c4tooltipVerspaetet'), @@ -358,6 +383,24 @@ export const AbgabeMitarbeiterDetail = { value: this.$p.t('abgabetool/c4tooltipAbgegeben'), class: "custom-tooltip" } + }, + getTooltipFixtermin() { + return { + value: this.$p.t('abgabetool/c4tooltipFixtermin'), + class: "custom-tooltip" + } + }, + getTooltipNotAllowedToSave() { + return { + value: this.$p.t('abgabetool/c4notAllowedToEditAbgabeTermin'), + class: "custom-tooltip" + } + }, + getTooltipNotAllowedToDelete() { + return { + value: this.$p.t('abgabetool/c4notAllowedToDeleteAbgabeTermin'), + class: "custom-tooltip" + } } }, watch: { @@ -378,23 +421,23 @@ export const AbgabeMitarbeiterDetail = { }, template: ` - - - + + `, }; diff --git a/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js b/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js index f79df80b5..9c1682537 100644 --- a/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js +++ b/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js @@ -48,7 +48,7 @@ export const AbgabeStudentDetail = { methods: { async validate(termin, endupload = false) { if(!termin.file.length) { - this.$fhcAlert.alertWarning(this.$p.t('global/warningChooseFile')); + this.$fhcAlert.alertWarning(this.$capitalize(this.$p.t('global/warningChooseFile'))); return false } @@ -57,49 +57,49 @@ export const AbgabeStudentDetail = { // check these input fields for length of entry if(this.form['abstract'].length < 100 && await this.$fhcAlert.confirm({ message: this.$p.t('abgabetool/warningShortAbstract'), - acceptLabel: this.$p.t('abgabetool/c4AcceptAndProceed'), + acceptLabel: this.$capitalize(this.$p.t('abgabetool/c4AcceptAndProceed')), acceptClass: 'btn btn-danger', - rejectLabel: this.$p.t('abgabetool/c4Cancel'), + rejectLabel: this.$capitalize(this.$p.t('abgabetool/c4Cancel')), rejectClass: 'btn btn-outline-secondary' }) === false) { return false } if(this.form['abstract_en'].length < 100 && await this.$fhcAlert.confirm({ - message: this.$p.t('abgabetool/warningShortAbstractEn'), - acceptLabel: this.$p.t('abgabetool/c4AcceptAndProceed'), + message: this.$capitalize(this.$p.t('abgabetool/warningShortAbstractEn')), + acceptLabel: this.$capitalize(this.$p.t('abgabetool/c4AcceptAndProceed')), acceptClass: 'btn btn-danger', - rejectLabel: this.$p.t('abgabetool/c4Cancel'), + rejectLabel: this.$capitalize(this.$p.t('abgabetool/c4Cancel')), rejectClass: 'btn btn-outline-secondary' }) === false) { return false } if(this.form['schlagwoerter'].length < 50 && await this.$fhcAlert.confirm({ - message: this.$p.t('abgabetool/warningShortSchlagwoerter'), - acceptLabel: this.$p.t('abgabetool/c4AcceptAndProceed'), + message: this.$capitalize(this.$p.t('abgabetool/warningShortSchlagwoerter')), + acceptLabel: this.$capitalize(this.$p.t('abgabetool/c4AcceptAndProceed')), acceptClass: 'btn btn-danger', - rejectLabel: this.$p.t('abgabetool/c4Cancel'), + rejectLabel: this.$capitalize(this.$p.t('abgabetool/c4Cancel')), rejectClass: 'btn btn-outline-secondary' }) === false) { return false } if(this.form['schlagwoerter_en'].length < 50 && await this.$fhcAlert.confirm({ - message: this.$p.t('abgabetool/warningShortSchlagwoerterEn'), - acceptLabel: this.$p.t('abgabetool/c4AcceptAndProceed'), + message: this.$capitalize(this.$p.t('abgabetool/warningShortSchlagwoerterEn')), + acceptLabel: this.$capitalize(this.$p.t('abgabetool/c4AcceptAndProceed')), acceptClass: 'btn btn-danger', - rejectLabel: this.$p.t('abgabetool/c4Cancel'), + rejectLabel: this.$capitalize(this.$p.t('abgabetool/c4Cancel')), rejectClass: 'btn btn-outline-secondary' }) === false) { return false } if(this.form['seitenanzahl'] <= 5 && await this.$fhcAlert.confirm({ - message: this.$p.t('abgabetool/warningSmallSeitenanzahl'), - acceptLabel: this.$p.t('abgabetool/c4AcceptAndProceed'), + message: this.$capitalize(this.$p.t('abgabetool/warningSmallSeitenanzahl')), + acceptLabel: this.$capitalize(this.$p.t('abgabetool/c4AcceptAndProceed')), acceptClass: 'btn btn-danger', - rejectLabel: this.$p.t('abgabetool/c4Cancel'), + rejectLabel: this.$capitalize(this.$p.t('abgabetool/c4Cancel')), rejectClass: 'btn btn-outline-secondary' }) === false) { return false @@ -192,13 +192,13 @@ export const AbgabeStudentDetail = { }, handleUploadRes(res, termin) { if(res.meta.status == "success") { - this.$fhcAlert.alertSuccess(this.$p.t('abgabetool/c4fileUploadSuccessv3')) + this.$fhcAlert.alertSuccess(this.$capitalize(this.$p.t('abgabetool/c4fileUploadSuccessv3'))) // update 'abgabedatum' for successful upload -> shows the pdf icon and date once set termin.abgabedatum = new Date().toISOString().split('T')[0]; } else { - this.$fhcAlert.alertError(this.$p.t('abgabetool/c4fileUploadErrorv3')) + this.$fhcAlert.alertError(this.$capitalize(this.$p.t('abgabetool/c4fileUploadErrorv3'))) } if(res.meta.signaturInfo) { @@ -262,8 +262,26 @@ export const AbgabeStudentDetail = { } }, computed: { + getActiveIndexTabArray() { + // here we try to do mind reading logic by assuming which abgabetermine are the most relevant to the current user + + // lets try to take the termin with nearest date and watch who complains and why + let closestIndex = -1; + let minDiff = Infinity; + const today = new Date(); + + this.projektarbeit.abgabetermine.forEach((obj, i) => { + const diff = Math.abs(new Date(obj.datum) - today); + if (diff < minDiff) { + minDiff = diff; + closestIndex = i; + } + }); + + return [closestIndex] + }, getEid() { - return this.$p.t('abgabetool/c4eidesstattlicheErklaerung') + return this.$capitalize(this.$p.t('abgabetool/c4eidesstattlicheErklaerung')) }, getAllowedToSendEndupload() { return !this.eidAkzeptiert @@ -280,37 +298,56 @@ export const AbgabeStudentDetail = { }, getTooltipVerspaetet() { return { - value: this.$p.t('abgabetool/c4tooltipVerspaetet'), + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipVerspaetet')), class: "custom-tooltip" } }, getTooltipVerpasst() { return { - value: this.$p.t('abgabetool/c4tooltipVerpasst'), + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipVerpasst')), class: "custom-tooltip" } }, getTooltipAbzugeben() { return { - value: this.$p.t('abgabetool/c4tooltipAbzugeben'), + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipAbzugeben')), class: "custom-tooltip" } }, getTooltipStandard() { return { - value: this.$p.t('abgabetool/c4tooltipStandard'), + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipStandard')), class: "custom-tooltip" } }, getTooltipAbgegeben() { return { - value: this.$p.t('abgabetool/c4tooltipAbgegeben'), + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipAbgegeben')), class: "custom-tooltip" } + }, + getTooltipFixtermin() { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipFixtermin')), + class: "custom-tooltip" + } + }, + getTooltipNotAllowedToUpload() { + if(this.isViewMode) { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4studentAbgabeNotAllowedInViewMode')), + class: "custom-tooltip" + } + } else { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4studentAbgabeNotAllowedRegular')), + class: "custom-tooltip" + } + } } }, created() { - + }, mounted() { @@ -320,16 +357,15 @@ export const AbgabeStudentDetail = { -
-
{{$p.t('abgabetool/c4abgabeStudentenbereich')}}
+
{{$capitalize( $p.t('abgabetool/c4abgabeStudentenbereich') )}}

{{projektarbeit?.betreuer}}

{{projektarbeit?.titel}}

- + `, }; diff --git a/public/js/components/Cis/Abgabetool/DeadlineOverview.js b/public/js/components/Cis/Abgabetool/DeadlineOverview.js index a5cc9a43b..1b842b27f 100644 --- a/public/js/components/Cis/Abgabetool/DeadlineOverview.js +++ b/public/js/components/Cis/Abgabetool/DeadlineOverview.js @@ -34,7 +34,7 @@ export const DeadlineOverview = { 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/c4fixterminv2')), 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/c4abgabetypv2')), 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}, diff --git a/public/js/helpers/StringHelpers.js b/public/js/helpers/StringHelpers.js new file mode 100644 index 000000000..27008192a --- /dev/null +++ b/public/js/helpers/StringHelpers.js @@ -0,0 +1,4 @@ +export function capitalize(string) { + if (!string) return ''; + return string[0].toUpperCase() + string.slice(1); +} diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 21ea22a20..33b9fb8de 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -42059,18 +42059,18 @@ array( array( 'app' => 'core', 'category' => 'abgabetool', - 'phrase' => 'c4abgabetyp', + 'phrase' => 'c4abgabetypv2', 'insertvon' => 'system', 'phrases' => array( array( 'sprache' => 'German', - 'text' => "Abgabetyp", + 'text' => "Projektfrist", 'description' => '', 'insertvon' => 'system' ), array( 'sprache' => 'English', - 'text' => "Type of document submitted", + 'text' => "Type of project deadline", 'description' => '', 'insertvon' => 'system' ) @@ -42916,6 +42916,78 @@ array( ) ) ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4tooltipFixtermin', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Für den gesamten Studiengang verbindlicher Termin. + + Liegt ein Termin in der Vergangenheit, kann nichts mehr hochgeladen werden. Ist es dennoch erforderlich, + haben Studierende bei der Studiengangsassistenz um eine Korrektur dieses Termins anzusuchen.", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'This deadline is binding for the entire program. If a deadline is in the past, + nothing can be uploaded. If it is still necessary, + students must request a correction of this deadline from the program assistant.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4notAllowedToEditAbgabeTermin', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Sie sind nicht berechtigt diesen Abgabetermin zu bearbeiten. + Es muss entweder eine Benotung vorgesehen sein oder sich um einen individuellen Termin handeln, + welcher von Ihrem Benutzerkonto angelegt wurde.", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'You are not authorized to edit this deadline. + It must either be scheduled for grading or be a custom due date + created by your user account.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4notAllowedToDeleteAbgabeTermin', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Sie sind nicht berechtigt diesen Abgabetermin zu löschen. + Sie benötigen mindestens die Berechtigung den Termin zu bearbeiten und es darf noch keine + Dateiabgabe vorhanden sein.", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'You are not authorized to delete this deadline. + You need at least the permission to edit the deadline, and no file submissions must yet exist.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'abgabetool', @@ -42936,6 +43008,50 @@ array( ) ) ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4studentAbgabeNotAllowedInViewMode', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Projektabgabe im Ansichtsmodus ist nicht erlaubt!", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Project submission in view mode is not allowed!', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4studentAbgabeNotAllowedRegular', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Verspätete Projektabgabe ist bei Terminen, welche von der Studiengangsassistenz für den gesamten Studiengang fixiert wurden nicht erlaubt! + + Um einen Endupload durchführen zu können, müssen Sie ein positiv benotetes Quality Gate 1 & Quality Gate 2 in der relevanten Projektarbeit absolviert haben.", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Late project submissions are not permitted for deadlines set by the program assistant for the entire program! + + To be able to complete a final upload, you must have successfully completed Quality Gate 1 and Quality Gate 2 for the relevant project work.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'abgabetool', diff --git a/vilesci/lehre/abgabe_assistenz.php b/vilesci/lehre/abgabe_assistenz.php index 6d46e98cd..ababd4b69 100644 --- a/vilesci/lehre/abgabe_assistenz.php +++ b/vilesci/lehre/abgabe_assistenz.php @@ -80,9 +80,9 @@ $trenner->loadVariables($getuid); $sql_query = "SELECT *, (SELECT orgform_kurzbz - FROM tbl_prestudentstatus - WHERE prestudent_id=(Select prestudent_id from tbl_student where student_uid=xy.uid limit 1) - ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1 + FROM tbl_prestudentstatus + WHERE prestudent_id=(Select prestudent_id from tbl_student where student_uid=xy.uid limit 1) + ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1 ) as organisationsform FROM (SELECT DISTINCT ON(tbl_projektarbeit.projektarbeit_id) public.tbl_studiengang.bezeichnung as stgbez,tbl_projekttyp.bezeichnung AS prjbez,* FROM lehre.tbl_projektarbeit LEFT JOIN public.tbl_benutzer on(uid=student_uid)