From 08182fe0f504132293ed16ead5ae262aa1e1ccbc Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 18 Jun 2025 12:03:09 +0200 Subject: [PATCH 001/185] Added phrases for LV-Evaluierung --- system/phrasesupdate.php | 428 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 427 insertions(+), 1 deletion(-) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 0203b3c2f..7c350c452 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -41873,8 +41873,434 @@ and represent the current state of research on the topic. The prescribed citatio 'insertvon' => 'system' ) ) - ) + ), // PROJEKTARBEITSBEURTEILUNG SS2025 ENDE --------------------------------------------------------------------------- + array( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'abschicken', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Abschicken', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Submit', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'zurueckZumStart', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Zurück zum Start', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Back to Start', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'global', + 'phrase' => 'lvevaluierungAbschicken', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'LV-Evaluierung abschicken', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Submit Course Evaluation', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'global', + 'phrase' => 'lvevaluierung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'LV-Evaluierung', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Course Evaluation', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'loginTextCodeEingeben', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Bitte geben Sie Ihren Code ein, um die Evaluierung zu starten:', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Please enter your code to start the evaluation:', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'loginCodeEingeben', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Evaluierung-Code eingeben', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Enter your Evaluation-Code', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'loginTextLvevaluierung', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => ' +
+

Die folgende LV-Evaluierung umfasst

+
+ + ', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => ' +
+

The following course evaluation includes

+
+ + ', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'loginTextAntwortoptionen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => ' +
+

Die Antwortoptionen umfassen 5 Stufen:

+
+ + ', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => ' +
+

The answer options comprise 5 levels:

+
+ + ', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungPeriodeBeendet', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Der Evaluierungszeitraum endete am {date}', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Evaluation period was closed on {date}', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungPeriodeStartetErst', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Der Evaluierungszeitraum startet erst am {date}', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Evaluation period starts on {date}', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungEingereicht', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Die Evaluierung wurde am {date} eingereicht', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Evaluation was submitted on {date}', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungNichtMehrVerfuegbar', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Diese Evaluierung ist nicht mehr verfügbar.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'This evaluation is no longer available.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungNichtVerfuegbar', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Diese Evaluierung ist nicht verfügbar.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'This evaluation is not available yet.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'logoutTitle', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Danke!
Was passiert nun mit Ihrem Feedback?', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Thank you!
What happens to your feedback now?', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'logoutText', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => ' +

Ihr Feedback dient den Lehrenden zur Selbstevaluierung und Ihre Jahrgangsvertretungen werden von der Studiengangsleitung zum Jour-Fixe eingeladen, um die Ergebnisse zu besprechen.

+

Ihr Feedback dient der kontinuierlichen Weiterentwicklung der Lehrveranstaltung. Mehr Details dazu finden Sie hier: + ', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => ' +

Your feedback is used by the lecturers for self-evaluation and your year representatives are invited to the Jour-Fixe by the head of degree program to discuss the results.

+

Your feedback is used for the continuous further development of the course. You can find more details here: + ', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungZeitAbgelaufen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Die Evaluierungszeit ist abgelaufen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'The Evaluation time is over', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungAntwortenNichtUebermittelt', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Ihre Antworten wurden nicht übermittelt.', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Your responses were not submitted.', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungCodeExistiertNicht', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Dieser Evaluierungscode exisitiert nicht', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'This evaluation code does not exist', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungNichtAktiv', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Die Evaluierung ist nicht aktiv', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Evaluation is not active', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), ); From fd2de106f8a4a760e1df0c001896022cc95a4ba9 Mon Sep 17 00:00:00 2001 From: Cristina Date: Tue, 24 Jun 2025 15:02:45 +0200 Subject: [PATCH 002/185] Added column evaluierung to lehre.tbl_lehrveranstaltung - evaluierung (boolean) indicates if lehrveranstaltung shall be evaluated. Default is true. --- system/dbupdate_3.4.php | 3 ++- system/dbupdate_3.4/62063_lv_evaluierung.php | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 system/dbupdate_3.4/62063_lv_evaluierung.php diff --git a/system/dbupdate_3.4.php b/system/dbupdate_3.4.php index 0e2b4e7c6..6b346573a 100644 --- a/system/dbupdate_3.4.php +++ b/system/dbupdate_3.4.php @@ -74,6 +74,7 @@ require_once('dbupdate_3.4/55968_index_anrechnung.php'); require_once('dbupdate_3.4/25999_locale_update.php'); require_once('dbupdate_3.4/55289_pep_fine_tuning.php'); require_once('dbupdate_3.4/55614_perm_verwaltetoe.php'); +require_once('dbupdate_3.4/62063_lv_evaluierung.php'); // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen echo '

Pruefe Tabellen und Attribute!

'; @@ -241,7 +242,7 @@ $tabellen=array( "lehre.tbl_lehrmittel" => array("lehrmittel_kurzbz","beschreibung","ort_kurzbz"), "lehre.tbl_lehrmodus" => array("lehrmodus_kurzbz","bezeichnung_mehrsprachig","aktiv"), "lehre.tbl_lehrtyp" => array("lehrtyp_kurzbz","bezeichnung"), - "lehre.tbl_lehrveranstaltung" => array("lehrveranstaltung_id","kurzbz","bezeichnung","lehrform_kurzbz","studiengang_kz","semester","sprache","ects","semesterstunden","anmerkung","lehre","lehreverzeichnis","aktiv","planfaktor","planlektoren","planpersonalkosten","plankostenprolektor","koordinator","sort","zeugnis","projektarbeit","updateamum","updatevon","insertamum","insertvon","ext_id","bezeichnung_english","orgform_kurzbz","incoming","lehrtyp_kurzbz","oe_kurzbz","raumtyp_kurzbz","anzahlsemester","semesterwochen","lvnr","farbe","semester_alternativ","old_lehrfach_id","sws","lvs","alvs","lvps","las","benotung","lvinfo","lehrauftrag","lehrmodus_kurzbz","lehrveranstaltung_template_id"), + "lehre.tbl_lehrveranstaltung" => array("lehrveranstaltung_id","kurzbz","bezeichnung","lehrform_kurzbz","studiengang_kz","semester","sprache","ects","semesterstunden","anmerkung","lehre","lehreverzeichnis","aktiv","planfaktor","planlektoren","planpersonalkosten","plankostenprolektor","koordinator","sort","zeugnis","projektarbeit","updateamum","updatevon","insertamum","insertvon","ext_id","bezeichnung_english","orgform_kurzbz","incoming","lehrtyp_kurzbz","oe_kurzbz","raumtyp_kurzbz","anzahlsemester","semesterwochen","lvnr","farbe","semester_alternativ","old_lehrfach_id","sws","lvs","alvs","lvps","las","benotung","lvinfo","lehrauftrag","lehrmodus_kurzbz","lehrveranstaltung_template_id", "evaluierung"), "lehre.tbl_lehrveranstaltung_kompatibel" => array("lehrveranstaltung_id","lehrveranstaltung_id_kompatibel"), "lehre.tbl_lvangebot" => array("lvangebot_id","lehrveranstaltung_id","studiensemester_kurzbz","gruppe_kurzbz","incomingplaetze","gesamtplaetze","anmeldefenster_start","anmeldefenster_ende","insertamum","insertvon","updateamum","updatevon"), "lehre.tbl_lvregel" => array("lvregel_id","lvregeltyp_kurzbz","operator","parameter","lvregel_id_parent","lehrveranstaltung_id","studienplan_lehrveranstaltung_id","insertamum","insertvon","updateamum","updatevon"), diff --git a/system/dbupdate_3.4/62063_lv_evaluierung.php b/system/dbupdate_3.4/62063_lv_evaluierung.php new file mode 100644 index 000000000..5a0714772 --- /dev/null +++ b/system/dbupdate_3.4/62063_lv_evaluierung.php @@ -0,0 +1,15 @@ +db_query("SELECT evaluierung FROM lehre.tbl_lehrveranstaltung LIMIT 1")) +{ + $qry = "ALTER TABLE lehre.tbl_lehrveranstaltung ADD COLUMN evaluierung boolean NOT NULL DEFAULT true; + COMMENT ON COLUMN lehre.tbl_lehrveranstaltung.evaluierung IS 'TRUE wenn für diese LV eine LV-Evaluierung durchgeführt wird'; + "; + + if(!$db->db_query($qry)) + echo 'lehre.tbl_lehrveranstaltung '.$db->db_last_error().'
'; + else + echo '
Spalte evaluierung zu Tabelle lehre.tbl_lehrveranstaltung hinzugefügt'; +} From 4b8af46a2ee0edf7968ec18c4204fd6d0e40d0cc Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 25 Jun 2025 13:30:05 +0200 Subject: [PATCH 003/185] Added 'evaluierung' to lehrveranstaltung.class.php and updated related methods --- include/lehrveranstaltung.class.php | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/include/lehrveranstaltung.class.php b/include/lehrveranstaltung.class.php index 48edd9d0a..aa3b6771e 100644 --- a/include/lehrveranstaltung.class.php +++ b/include/lehrveranstaltung.class.php @@ -70,6 +70,7 @@ class lehrveranstaltung extends basis_db public $farbe; public $lehrauftrag=true; public $lehrveranstaltung_template_id; // integer + public $evaluierung=true; // boolean public $studienplan_lehrveranstaltung_id; @@ -170,6 +171,7 @@ class lehrveranstaltung extends basis_db $this->benotung = $this->db_parse_bool($row->benotung); $this->lvinfo = $this->db_parse_bool($row->lvinfo); $this->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $this->evaluierung = $this->db_parse_bool($row->evaluierung); // FIXME: LV-Bezeichnung richtig mehrsprachig machen // Zwischenzeitlich 'Italian' zum bezeichnung_arr dazugegeben @@ -244,6 +246,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -394,6 +397,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['Italian'] = $row->bezeichnung; @@ -524,6 +528,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -607,6 +612,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -779,7 +785,7 @@ class lehrveranstaltung extends basis_db insertvon, planfaktor, planlektoren, planpersonalkosten, plankostenprolektor, updateamum, updatevon, sort, zeugnis, projektarbeit, sprache, koordinator, bezeichnung_english, orgform_kurzbz, incoming, lehrtyp_kurzbz, oe_kurzbz, raumtyp_kurzbz, anzahlsemester, semesterwochen, lvnr, semester_alternativ, farbe, lehrveranstaltung_template_id,sws,lvs,alvs,lvps,las,benotung,lvinfo, - lehrauftrag, lehrmodus_kurzbz) VALUES ('. + lehrauftrag, lehrmodus_kurzbz, evaluierung) VALUES ('. $this->db_add_param($this->studiengang_kz). ', '. $this->db_add_param($this->bezeichnung). ', '. $this->db_add_param($this->kurzbz). ', '. @@ -824,7 +830,8 @@ class lehrveranstaltung extends basis_db $this->db_add_param($this->benotung, FHC_BOOLEAN).','. $this->db_add_param($this->lvinfo, FHC_BOOLEAN).','. $this->db_add_param($this->lehrauftrag, FHC_BOOLEAN).','. - $this->db_add_param($this->lehrmodus_kurzbz) + $this->db_add_param($this->lehrmodus_kurzbz).','. + $this->db_add_param($this->evaluierung, FHC_BOOLEAN) .');'; } else @@ -880,7 +887,8 @@ class lehrveranstaltung extends basis_db 'las = '.$this->db_add_param($this->las).', '. 'benotung = '.$this->db_add_param($this->benotung, FHC_BOOLEAN).', '. 'lvinfo = '.$this->db_add_param($this->lvinfo, FHC_BOOLEAN).', '. - 'lehrauftrag = '.$this->db_add_param($this->lehrauftrag, FHC_BOOLEAN).' '. + 'lehrauftrag = '.$this->db_add_param($this->lehrauftrag, FHC_BOOLEAN).', '. + 'evaluierung = '.$this->db_add_param($this->evaluierung, FHC_BOOLEAN).' '. 'WHERE lehrveranstaltung_id = ' . $this->db_add_param($this->lehrveranstaltung_id, FHC_INTEGER, false) . ';'; } @@ -991,6 +999,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -1086,6 +1095,7 @@ class lehrveranstaltung extends basis_db $l->benotung = $this->db_parse_bool($row->benotung); $l->lvinfo = $this->db_parse_bool($row->lvinfo); $l->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $l->evaluierung = $this->db_parse_bool($row->evaluierung); $l->bezeichnung_arr['German'] = $row->bezeichnung; $l->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -1170,6 +1180,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -1271,6 +1282,7 @@ class lehrveranstaltung extends basis_db $obj->benotung = $this->db_parse_bool($row->benotung); $obj->lvinfo = $this->db_parse_bool($row->lvinfo); $obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $obj->evaluierung = $this->db_parse_bool($row->evaluierung); $obj->bezeichnung_arr['German'] = $row->bezeichnung; $obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -1396,6 +1408,7 @@ class lehrveranstaltung extends basis_db $obj->lvinfo =$this->db_parse_bool( $lv->lvinfo); $obj->zeugnis = $this->db_parse_bool($lv->zeugnis); $obj->lehrauftrag = $this->db_parse_bool($lv->lehrauftrag); + $obj->evaluierung = $this->db_parse_bool($lv->evaluierung); $values[] = $obj; @@ -1422,6 +1435,7 @@ class lehrveranstaltung extends basis_db $obj->lvinfo =$this->db_parse_bool( $this->lvinfo); $obj->zeugnis = $this->db_parse_bool($this->zeugnis); $obj->lehrauftrag = $this->db_parse_bool($this->lehrauftrag); + $obj->evaluierung = $this->db_parse_bool($this->evaluierung); $values[] = $obj; } @@ -1476,6 +1490,7 @@ class lehrveranstaltung extends basis_db $obj->export = $lv->export; $obj->genehmigung = $lv->genehmigung; $obj->lehrauftrag = $lv->lehrauftrag; + $obj->evaluierung = $lv->evaluierung; $obj->lehre = $lv->lehre; $obj->children = array(); if(count($lv->childs) > 0) @@ -1507,6 +1522,7 @@ class lehrveranstaltung extends basis_db $obj->zeugnis = $this->db_parse_bool($this->zeugnis); $obj->curriculum = $this->db_parse_bool($this->curriculum); $obj->lehrauftrag = $this->lehrauftrag; + $obj->evaluierung = $this->db_parse_bool($this->evaluierung); $values[] = $obj; } @@ -1613,6 +1629,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -1700,6 +1717,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -1873,6 +1891,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -2003,6 +2022,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->studiengang_kurzbzlang = $row->studiengang_kurzbzlang; @@ -2131,6 +2151,7 @@ class lehrveranstaltung extends basis_db $lv_obj->benotung = $this->db_parse_bool($row->benotung); $lv_obj->lvinfo = $this->db_parse_bool($row->lvinfo); $lv_obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $lv_obj->evaluierung = $this->db_parse_bool($row->evaluierung); $lv_obj->bezeichnung_arr['German'] = $row->bezeichnung; $lv_obj->bezeichnung_arr['English'] = $row->bezeichnung_english; @@ -2402,6 +2423,7 @@ class lehrveranstaltung extends basis_db $obj->benotung = $this->db_parse_bool($row->benotung); $obj->lvinfo = $this->db_parse_bool($row->lvinfo); $obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag); + $obj->evaluierung = $this->db_parse_bool($row->evaluierung); $obj->bezeichnung_arr['German'] = $row->bezeichnung; $obj->bezeichnung_arr['English'] = $row->bezeichnung_english; From daf9d2ea15f8d7063a07cf179cb87cdd8cda8d31 Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 25 Jun 2025 13:35:20 +0200 Subject: [PATCH 004/185] Added checkbox 'evaluierung' Lehrveranstaltung Details in VILESCI --- vilesci/lehre/lehrveranstaltung_details.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vilesci/lehre/lehrveranstaltung_details.php b/vilesci/lehre/lehrveranstaltung_details.php index bad2a7d93..c1433047c 100644 --- a/vilesci/lehre/lehrveranstaltung_details.php +++ b/vilesci/lehre/lehrveranstaltung_details.php @@ -122,6 +122,7 @@ $lv->benotung = isset($_POST['benotung']); $lv->lvinfo = isset($_POST['lvinfo']); $lv->lehrauftrag = isset($_POST['lehrauftrag']); + $lv->evaluierung = isset($_POST['evaluierung']); $lv->lehrveranstaltung_template_id = $lv->lehrtyp_kurzbz == 'tpl' ? '' : $_POST['lehrveranstaltung_template_id']; if(!$lv->save()) @@ -446,6 +447,10 @@ Lehrauftrag lehrauftrag?'checked':'').'> + + Evaulierung + evaluierung?'checked':'').'> + Template From 56bfe46675ff6281ca454073c486c55399b3e7fb Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 2 Jul 2025 12:10:28 +0200 Subject: [PATCH 005/185] Added phrases for lvevaluierung --- system/phrasesupdate.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 7c350c452..8ac45c0fa 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -41915,6 +41915,7 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + // LVEVALUIERUNG --------------------------------------------------------------------------------------------------- array( 'app' => 'lvevaluierung', 'category' => 'global', @@ -42301,6 +42302,26 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'zeitLaeuftAb', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Zeit läuft bald ab – zum Speichern bitte ‚Abschicken‘ klicken', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Time is running out — please click ‘Submit’ to save your answers', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), ); From 153e273fec5396c5bd0991867a3b38b5335ab54f Mon Sep 17 00:00:00 2001 From: ma0048 Date: Wed, 9 Jul 2025 13:52:46 +0200 Subject: [PATCH 006/185] firefox check entfernt --- cis/testtool/login.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/cis/testtool/login.php b/cis/testtool/login.php index 5a2ae0dea..5306dadab 100644 --- a/cis/testtool/login.php +++ b/cis/testtool/login.php @@ -447,14 +447,6 @@ if (isset($_POST['save']) && isset($_SESSION['prestudent_id'])) { e.preventDefault(); }); - // If Browser is any other than Mozilla Firefox and the test includes any MathML, - // show message to use Mozilla Firefox - var ua = navigator.userAgent; - if ((ua.indexOf("Firefox") > -1) == false) - { - $("#alertmsgdiv").html("
BITTE VERWENDEN SIE DEN MOZILLA FIREFOX BROWSER!
(Manche Prüfungsfragen werden sonst nicht korrekt dargestellt.

PLEASE USE MOZILLA FIREFOX BROWSER!
(Otherwise some exam items will not be displayed correctly
"); - //alert('BITTE VERWENDEN SIE DEN MOZILLA FIREFOX BROWSER!\n(Manche Prüfungsfragen werden sonst nicht korrekt dargestellt.\n\nPLEASE USE MOZILLA FIREFOX BROWSER!\n(Ohterwise some exam items will not be displayed correctly.)'); - } }); Date: Wed, 16 Jul 2025 16:13:27 +0200 Subject: [PATCH 007/185] Added phrases for lvevaluierung --- system/phrasesupdate.php | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 8ac45c0fa..417eb9110 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -42322,6 +42322,86 @@ and represent the current state of research on the topic. The prescribed citatio ) ) ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'spracheAuswaehlen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Sprache auswählen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Select language', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'fhtwLogo', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'FH Technikum Wien Logo', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'UAS Technikum Wien Logo', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungscodeEingeben', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Evaluierungscode eingeben', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Enter Evaluation code', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'fragebogen', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Fragebogen', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Questionnaire', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), ); From 483662726deded3970b676dd4cf88da2dd21755c Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Fri, 22 Aug 2025 14:40:58 +0200 Subject: [PATCH 008/185] abgabetool api/controller refactor; quality gates dbupdate script; load types from backend instead of hardcoded; WIP email check for externe betreuer; --- .../controllers/api/frontend/v1/Abgabe.php | 647 ++++++++++++++++++ .../controllers/api/frontend/v1/Lehre.php | 579 +--------------- .../models/education/Paabgabetyp_model.php | 6 + public/js/api/factory/abgabe.js | 96 +++ public/js/api/lehre.js | 75 -- .../Cis/Abgabetool/AbgabeMitarbeiterDetail.js | 8 +- .../Cis/Abgabetool/AbgabeStudentDetail.js | 9 +- .../Cis/Abgabetool/AbgabetoolMitarbeiter.js | 17 +- .../Cis/Abgabetool/AbgabetoolStudent.js | 4 +- .../Cis/Abgabetool/DeadlineOverview.js | 2 +- .../61164_abgabetool_quality_gates.php | 29 + 11 files changed, 805 insertions(+), 667 deletions(-) create mode 100644 application/controllers/api/frontend/v1/Abgabe.php create mode 100644 public/js/api/factory/abgabe.js create mode 100644 system/dbupdate_3.4/61164_abgabetool_quality_gates.php diff --git a/application/controllers/api/frontend/v1/Abgabe.php b/application/controllers/api/frontend/v1/Abgabe.php new file mode 100644 index 000000000..61a3b4c44 --- /dev/null +++ b/application/controllers/api/frontend/v1/Abgabe.php @@ -0,0 +1,647 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +//require_once('../../../include/studiengang.class.php'); +//require_once('../../../include/student.class.php'); +//require_once('../../../include/datum.class.php'); +//require_once('../../../include/mail.class.php'); +//require_once('../../../include/benutzerberechtigung.class.php'); +//require_once('../../../include/phrasen.class.php'); +//require_once('../../../include/projektarbeit.class.php'); +//require_once('../../../include/projektbetreuer.class.php'); + +class Lehre extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'getStudentProjektarbeiten' => self::PERM_LOGGED, // TODO: abgabetool berechtigung? + 'getStudentProjektabgaben' => self::PERM_LOGGED, + 'postStudentProjektarbeitZwischenabgabe' => self::PERM_LOGGED, + 'postStudentProjektarbeitEndupload' => self::PERM_LOGGED, + 'getMitarbeiterProjektarbeiten' => self::PERM_LOGGED, + 'postProjektarbeitAbgabe' => self::PERM_LOGGED, + 'deleteProjektarbeitAbgabe' => self::PERM_LOGGED, + 'postSerientermin' => self::PERM_LOGGED, + 'fetchDeadlines' => self::PERM_LOGGED, // TODO: mitarbeiter recht prüfen + 'getPaAbgabetypen' => self::PERM_LOGGED + ]); + + $this->load->library('PhrasesLib'); + + $this->loadPhrases( + array( + 'global', + 'ui', + 'abgabetool' + ) + ); + + $this->load->helper('hlp_sancho_helper'); + + require_once(FHCPATH . 'include/studiengang.class.php'); + require_once(FHCPATH . 'include/student.class.php'); + require_once(FHCPATH . 'include/projektarbeit.class.php'); + require_once(FHCPATH . 'include/projektbetreuer.class.php'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * fetches all projektabgabetermine for a given projektarbeit_id used in cis4 student abgabetool + */ + public function getStudentProjektabgaben() { + $projektarbeit_id = $this->input->get("projektarbeit_id",TRUE); + + // TODO: error messages + + if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + $projektarbeit_obj = new projektarbeit(); + if($projektarbeit_id==-1) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + if(!$projektarbeit_obj->load($projektarbeit_id)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + $paIsCurrent = $projektarbeit_obj->projektarbeitIsCurrent($projektarbeit_id); + + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $ret = $this->ProjektarbeitModel->getProjektarbeitAbgabetermine($projektarbeit_id); + + // TODO: fetch zweitbetreuer + + $this->terminateWithSuccess(array($ret, $paIsCurrent)); + } + + /** + * fetches all projektarbeiten and betreuer for a given student_uid used in cis4 student abgabetool + */ + public function getStudentProjektarbeiten($uid) + { + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + if (!isset($uid) || isEmptyString($uid)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + $isZugeteilterBetreuer = count($this->ProjektarbeitModel->checkZuordnung($uid, getAuthUID())->retval) > 0; + $this->addMeta('isZugeteilterBetreuer', $isZugeteilterBetreuer); + $isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID()); + + if ($isMitarbeiter && $isZugeteilterBetreuer){ + $projektarbeiten = $this->ProjektarbeitModel->getStudentProjektarbeitenWithBetreuer($uid); + } else { + $projektarbeiten = $this->ProjektarbeitModel->getStudentProjektarbeitenWithBetreuer(getAuthUID()); + } + + $this->terminateWithSuccess(array($projektarbeiten, DOMAIN, $uid)); + } + + + + /** + * projektarbeit - upload for zwischenabgaben in cis4 student abgabetool + */ + public function postStudentProjektarbeitZwischenabgabe() + { + + $projektarbeit_id = $_POST['projektarbeit_id']; + $paabgabe_id = $_POST['paabgabe_id']; + $student_uid = $_POST['student_uid']; + $bperson_id = $_POST['bperson_id']; + $paabgabetyp_kurzbz = $_POST['paabgabetyp_kurzbz']; + + if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id) + || !isset($paabgabe_id) || isEmptyString($paabgabe_id) + || !isset($student_uid) || isEmptyString($student_uid) + || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + if ((isset($_FILES) and isset($_FILES['file']) and ! $_FILES['file']['error'])) { + move_uploaded_file($_FILES['file']['tmp_name'], PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'); + + if(file_exists(PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf')) { + + exec('chmod 640 "'.PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'.'"'); + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $res = $this->PaabgabeModel->update($paabgabe_id, array( + 'abgabedatum' => date('Y-m-d'), + 'updatevon' => getAuthUID(), + 'updateamum' => date('Y-m-d H:i:s') + )); + + $this->sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid); + $this->terminateWithSuccess($res); + } else { + $this->terminateWithError('Error moving File'); + } + + } else { + $this->terminateWithError('File missing'); + } + + } + + /** + * upload für finale abgaben aka Endupload in cis4 student abgabetool + */ + public function postStudentProjektarbeitEndupload() + { + + $projektarbeit_id = $_POST['projektarbeit_id']; + $paabgabe_id = $_POST['paabgabe_id']; + $student_uid = $_POST['student_uid']; + $sprache = $_POST['sprache']; + $abstract = $_POST['abstract']; + $abstract_en = $_POST['abstract_en']; + $schlagwoerter = $_POST['schlagwoerter']; + $schlagwoerter_en = $_POST['schlagwoerter_en']; + $seitenanzahl = $_POST['seitenanzahl']; + $bperson_id = $_POST['bperson_id']; + $paabgabetyp_kurzbz = $_POST['paabgabetyp_kurzbz']; + + if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id) + || !isset($paabgabe_id) || isEmptyString($paabgabe_id) + || !isset($student_uid) || isEmptyString($student_uid) + || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + // TODO: maybe check for other params aswell? + + if ((isset($_FILES) and isset($_FILES['file']) and ! $_FILES['file']['error'])) { + move_uploaded_file($_FILES['file']['tmp_name'], PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'); + + if(file_exists(PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf')) { + + // Loads Libraries + $this->load->library('SignatureLib'); + + // Check if the document is signed + $signaturVorhanden = true; + $signList = SignatureLib::list(PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'); + if (is_array($signList) && count($signList) > 0) + { + // The document is signed + $uploadedDocumentSigned = 'The document is signed'; + } + elseif ($signList === null) + { + $uploadedDocumentSigned = 'WARNING: signature server error'; + } + else + { + $signaturVorhanden = false; + $uploadedDocumentSigned = 'No document signature found'; + } + $this->addMeta('signaturInfo', $uploadedDocumentSigned); + + if ($signaturVorhanden === false) + { + $this->signaturFehltEmail($student_uid); + } + + // TODO error handle get data has data the updates + // update projektarbeit cols + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $this->ProjektarbeitModel->updateProjektarbeit($projektarbeit_id,$sprache,$abstract,$abstract_en + ,$schlagwoerter, $schlagwoerter_en, $seitenanzahl); + + + // update paabgabe datum + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $res = $this->PaabgabeModel->update($paabgabe_id, array( + 'abgabedatum' => date('Y-m-d'), + 'updatevon' => getAuthUID(), + 'updateamum' => date('Y-m-d H:i:s') + )); + + $this->sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid); + + $this->terminateWithSuccess($res); + } else { + $this->terminateWithError('Error moving File'); + } + + } else { + $this->terminateWithError('File missing'); + } + + } + + private function signaturFehltEmail($student_uid) { + + + // Mail an Studiengang wenn keine Signatur gefunden wurde + $student = new student(); + if(!$student->load($student_uid)) + $this->terminateWithError($this->p->t('global','userNichtGefunden'), 'general'); + + $stg_obj = new studiengang(); + if(!$stg_obj->load($student->studiengang_kz)) + $this->terminateWithError($this->p->t('global','fehlerBeimLesenAusDatenbank'), 'general'); + + $subject = 'Abgabe ohne Signatur'; + $tomail = $stg_obj->email; + $data = array( + 'vorname' => $student->vorname, + 'nachname' => $student->nachname, + 'studiengang' => $stg_obj->bezeichnung + ); + + $mailres = sendSanchoMail( + 'ParbeitsbeurteilungSiganturFehlt', + $data, + $tomail, + $subject, + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg' + ); + } + + private function sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid) { + + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $resBetr = $this->ProjektarbeitModel->getProjektbetreuerAnrede($bperson_id); + + $projektarbeit_obj = new projektarbeit(); + + if(!$projektarbeit_obj->load($projektarbeit_id)) + $this->terminateWithError('Ungueltiger Eintrag'); + + $num_rows_sem = $projektarbeit_obj->projektarbeitIsCurrent($projektarbeit_id); + + if( null === $num_rows_sem || false === $num_rows_sem ) + { + $this->terminateWithError($this->p->t('abgabetool','fehlerAktualitaetProjektarbeit'), 'general'); + } + + foreach($resBetr->retval as $betreuerRow) { + + // query student benutzer view for every betreuer row + $studentUser = $this->ProjektarbeitModel->getProjektarbeitBenutzer($student_uid)->retval[0]; + + // TODO: hasdata, getData etc + + // 1. Begutachter mail ohne Token + $mail_baselink = APP_ROOT."index.ci.php/extensions/FHC-Core-Projektarbeitsbeurteilung/ProjektarbeitsbeurteilungErstbegutachter"; + $mail_fulllink = "$mail_baselink?projektarbeit_id=".$projektarbeit_id."&uid=".$studentUser->uid; + $projekttyp_kurzbz = $projektarbeit_obj->projekttyp_kurzbz; + $subject = $projektarbeit_obj->projekttyp_kurzbz == 'Diplom' ? 'Masterarbeitsbetreuung' : 'Bachelorarbeitsbetreuung'; + $abgabetyp = $paabgabetyp_kurzbz == 'end' ? 'Endabgabe' : 'Zwischenabgabe'; + + $maildata = array(); + $maildata['geehrt'] = "geehrte".($betreuerRow->anrede=="Herr"?"r":""); + $maildata['anrede'] = $betreuerRow->anrede; + $maildata['betreuer_voller_name'] = $betreuerRow->first; + $maildata['student_anrede'] = $studentUser->anrede; + $maildata['student_voller_name'] = trim($studentUser->titelpre." ".$studentUser->vorname." ".$studentUser->nachname." ".$studentUser->titelpost); + $maildata['abgabetyp'] = $abgabetyp; + $maildata['parbeituebersichtlink'] = "

Zur Projektarbeitsübersicht

"; + $maildata['bewertunglink'] = $num_rows_sem >= 1 && $paabgabetyp_kurzbz == 'end' ? "

Zur Beurteilung der Arbeit

" : ""; + $maildata['token'] = ""; + + $email = $this->getBetreuerEmail($bperson_id); + + if(!$email) $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailBegutachter'), 'general'); + + $mailres = sendSanchoMail( + 'ParbeitsbeurteilungEndupload', + $maildata, + $email, +// $betreuerRow->mitarbeiter_uid."@".DOMAIN, + $subject, + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg', + get_uid()."@".DOMAIN); + + if(!$mailres) + { + $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailBegutachter'), 'general'); + } + + // 2. Begutachter mail, wenn Endabgabe, mit Token wenn extern + if ($paabgabetyp_kurzbz == 'end') + { + // Zweitbegutachter holen + $zweitbegutachter = new projektbetreuer(); + $zweitbegutachterRes = $zweitbegutachter->getZweitbegutachterWithToken($bperson_id, $projektarbeit_id, $studentUser->uid); + + if ($zweitbegutachterRes) + { + $zweitbegutachterResults = $zweitbegutachter->result; + + foreach ($zweitbegutachterResults as $begutachter) + { + // token generieren, wenn noch nicht vorhanden und notwendig (wird in methode überprüft) + $tokenGenRes = $zweitbegutachter->generateZweitbegutachterToken($begutachter->person_id, $projektarbeit_id); + + if (!$tokenGenRes) + { + $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailZweitBegutachter'), 'general'); + } + + // Zweitbegutachter (evtl. mit Token) holen + $zweitbegutachterMitToken = new projektbetreuer(); + $begutachterMitTokenRes = $zweitbegutachterMitToken->getZweitbegutachterWithToken($bperson_id, $projektarbeit_id, $studentUser->uid, $begutachter->person_id); + + if (!$begutachterMitTokenRes) + { + $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailZweitBegutachter'), 'general'); + } + + // Email an Zweitbegutachter senden + if (isset($zweitbegutachterMitToken->result[0])) + { + $begutachterMitToken = $zweitbegutachterMitToken->result[0]; + + $path = $begutachterMitToken->betreuerart_kurzbz == 'Zweitbegutachter' ? 'ProjektarbeitsbeurteilungZweitbegutachter' : 'ProjektarbeitsbeurteilungErstbegutachter'; + $mail_baselink = APP_ROOT."index.ci.php/extensions/FHC-Core-Projektarbeitsbeurteilung/$path"; + $mail_fulllink = "$mail_baselink?projektarbeit_id=".$projektarbeit_id."&uid=".$studentUser->uid; + $intern = isset($begutachterMitToken->uid); + $mail_link = $intern ? $mail_fulllink : $mail_baselink; + + $zweitbetmaildata = array(); + $zweitbetmaildata['geehrt'] = "geehrte" . ($begutachterMitToken->anrede == "Herr" ? "r" : ""); + $zweitbetmaildata['anrede'] = $begutachterMitToken->anrede; + $zweitbetmaildata['betreuer_voller_name'] = $begutachterMitToken->voller_name; + $zweitbetmaildata['student_anrede'] = $maildata['student_anrede']; + $zweitbetmaildata['student_voller_name'] = $maildata['student_voller_name']; + $zweitbetmaildata['abgabetyp'] = $abgabetyp; + $zweitbetmaildata['parbeituebersichtlink'] = $intern ? $maildata['parbeituebersichtlink'] : ""; + $zweitbetmaildata['bewertunglink'] = $num_rows_sem >= 1 ? "

Zur Beurteilung der Arbeit

" : ""; + $zweitbetmaildata['token'] = $num_rows_sem >= 1 && isset($begutachterMitToken->zugangstoken) && !$intern ? "

Zugangstoken: " . $begutachterMitToken->zugangstoken . "

" : ""; + + $mailres = sendSanchoMail( + 'ParbeitsbeurteilungEndupload', + $zweitbetmaildata, + $begutachterMitToken->email, + $subject, + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg', + get_uid()."@".DOMAIN + ); + + if (!$mailres) + { + $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailBegutachter'), 'general'); + } + } + } + } + } + } + } + + public function getMitarbeiterProjektarbeiten() { + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $boolParamStr = $this->input->get('showall'); + $trueStrings = ['true', '1']; + $falseStrings = ['false', '0']; + + // Handle missing or invalid parameter + if ($boolParamStr === null) { + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + $boolParamStrLower = strtolower($boolParamStr); + + if (in_array($boolParamStrLower, $trueStrings, true)) { + $showAllBool = true; + } elseif (in_array($boolParamStrLower, $falseStrings, true)) { + $showAllBool = false; + } else { +// $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + + $projektarbeiten = $this->ProjektarbeitModel->getMitarbeiterProjektarbeiten(getAuthUID(), $showAllBool); + + $this->terminateWithSuccess(array($projektarbeiten, DOMAIN)); + } + + public function postProjektarbeitAbgabe() { + $projektarbeit_id = $_POST['projektarbeit_id']; + $paabgabe_id = $_POST['paabgabe_id']; + $paabgabetyp_kurzbz = $_POST['paabgabetyp_kurzbz']; + $datum = $_POST['datum']; + $fixtermin = $_POST['fixtermin']; + $kurzbz = $_POST['kurzbz']; + + if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id) + || !isset($paabgabe_id) || isEmptyString($paabgabe_id) + || !isset($datum) || isEmptyString($datum) + || !isset($datum) || isEmptyString($datum) + || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + + if($paabgabe_id == -1) { + $result = $this->PaabgabeModel->insert( + array( + 'projektarbeit_id' => $projektarbeit_id, + 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, + 'fixtermin' => $fixtermin, + 'datum' => $datum, + 'kurzbz' => $kurzbz, + 'insertvon' => getAuthUID(), + 'insertamum' => date('Y-m-d H:i:s') + ) + ); + + $this->terminateWithSuccess($result); + } else { + $result = $this->PaabgabeModel->update( + $paabgabe_id, + array( + 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, + 'datum' => $datum, + 'kurzbz' => $kurzbz, + 'updatevon' => getAuthUID(), + 'updateamum' => date('Y-m-d H:i:s') + ) + ); + + $this->terminateWithSuccess($result); + } + } + + public function deleteProjektarbeitAbgabe() { + $paabgabe_id = $_POST['paabgabe_id']; + + if (!isset($paabgabe_id) || isEmptyString($paabgabe_id)) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + + $result = $this->PaabgabeModel->load($paabgabe_id); + $result = $this->getDataOrTerminateWithError($result); + + if(count($result) == 0) + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + + // TODO: berechtigung? + if($result[0]->insertvon === getAuthUID()) { + $result = $this->PaabgabeModel->delete($paabgabe_id); + $result = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($result); + } + + $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( + 'neuerAbgabetermin', + $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); + } + + public function getPaAbgabetypen() { + $this->load->model('education/Paabgabetyp_model', 'PaabgabetypModel'); + + $result = $this->PaabgabetypModel->getAll(); + $paabgabetypen = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($paabgabetypen); + } + + private function getBetreuerEmail($person_id) { + // check if betreuer is intern (fixangestellt = true) + // -> email: uid@DOMAIN + + // if betreuer is extern, check if there are private email contacts + // in tbl_kontakt. if so, return them + + return null; + } +} + diff --git a/application/controllers/api/frontend/v1/Lehre.php b/application/controllers/api/frontend/v1/Lehre.php index d5d0282bd..10d945a3e 100644 --- a/application/controllers/api/frontend/v1/Lehre.php +++ b/application/controllers/api/frontend/v1/Lehre.php @@ -38,34 +38,9 @@ class Lehre extends FHCAPI_Controller parent::__construct([ 'lvStudentenMail' => self::PERM_LOGGED, 'LV' => self::PERM_LOGGED, - 'Pruefungen' => self::PERM_LOGGED, - 'getStudentProjektarbeiten' => self::PERM_LOGGED, // TODO: abgabetool berechtigung? - 'getStudentProjektabgaben' => self::PERM_LOGGED, - 'postStudentProjektarbeitZwischenabgabe' => self::PERM_LOGGED, - 'postStudentProjektarbeitEndupload' => self::PERM_LOGGED, - 'getMitarbeiterProjektarbeiten' => self::PERM_LOGGED, - 'postProjektarbeitAbgabe' => self::PERM_LOGGED, - 'deleteProjektarbeitAbgabe' => self::PERM_LOGGED, - 'postSerientermin' => self::PERM_LOGGED, - 'fetchDeadlines' => self::PERM_LOGGED // TODO: mitarbeiter recht prüfen + 'Pruefungen' => self::PERM_LOGGED ]); - - $this->load->library('PhrasesLib'); - - $this->loadPhrases( - array( - 'global', - 'ui', - 'abgabetool' - ) - ); - - $this->load->helper('hlp_sancho_helper'); - require_once(FHCPATH . 'include/studiengang.class.php'); - require_once(FHCPATH . 'include/student.class.php'); - require_once(FHCPATH . 'include/projektarbeit.class.php'); - require_once(FHCPATH . 'include/projektbetreuer.class.php'); } //------------------------------------------------------------------------------------------------------------------ @@ -125,557 +100,5 @@ class Lehre extends FHCAPI_Controller $this->terminateWithSuccess($result); } - - /** - * fetches all projektabgabetermine for a given projektarbeit_id used in cis4 student abgabetool - */ - public function getStudentProjektabgaben() { - $projektarbeit_id = $this->input->get("projektarbeit_id",TRUE); - - // TODO: error messages - - if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id)) - $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); - - $projektarbeit_obj = new projektarbeit(); - if($projektarbeit_id==-1) - $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); - - if(!$projektarbeit_obj->load($projektarbeit_id)) - $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); - - $paIsCurrent = $projektarbeit_obj->projektarbeitIsCurrent($projektarbeit_id); - - $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); - $ret = $this->ProjektarbeitModel->getProjektarbeitAbgabetermine($projektarbeit_id); - - // TODO: fetch zweitbetreuer - - $this->terminateWithSuccess(array($ret, $paIsCurrent)); - } - - /** - * fetches all projektarbeiten and betreuer for a given student_uid used in cis4 student abgabetool - */ - public function getStudentProjektarbeiten($uid) - { - $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); - $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); - - if (!isset($uid) || isEmptyString($uid)) - $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); - - $isZugeteilterBetreuer = count($this->ProjektarbeitModel->checkZuordnung($uid, getAuthUID())->retval) > 0; - $this->addMeta('isZugeteilterBetreuer', $isZugeteilterBetreuer); - $isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID()); - - if ($isMitarbeiter && $isZugeteilterBetreuer){ - $projektarbeiten = $this->ProjektarbeitModel->getStudentProjektarbeitenWithBetreuer($uid); - } else { - $projektarbeiten = $this->ProjektarbeitModel->getStudentProjektarbeitenWithBetreuer(getAuthUID()); - } - - $this->terminateWithSuccess(array($projektarbeiten, DOMAIN, $uid)); - } - - - - /** - * projektarbeit - upload for zwischenabgaben in cis4 student abgabetool - */ - public function postStudentProjektarbeitZwischenabgabe() - { - - $projektarbeit_id = $_POST['projektarbeit_id']; - $paabgabe_id = $_POST['paabgabe_id']; - $student_uid = $_POST['student_uid']; - $bperson_id = $_POST['bperson_id']; - $paabgabetyp_kurzbz = $_POST['paabgabetyp_kurzbz']; - - if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id) - || !isset($paabgabe_id) || isEmptyString($paabgabe_id) - || !isset($student_uid) || isEmptyString($student_uid) - || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) - $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); - - if ((isset($_FILES) and isset($_FILES['file']) and ! $_FILES['file']['error'])) { - move_uploaded_file($_FILES['file']['tmp_name'], PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'); - - if(file_exists(PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf')) { - - exec('chmod 640 "'.PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'.'"'); - - $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); - $res = $this->PaabgabeModel->update($paabgabe_id, array( - 'abgabedatum' => date('Y-m-d'), - 'updatevon' => getAuthUID(), - 'updateamum' => date('Y-m-d H:i:s') - )); - - $this->sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid); - $this->terminateWithSuccess($res); - } else { - $this->terminateWithError('Error moving File'); - } - - } else { - $this->terminateWithError('File missing'); - } - - } - - /** - * upload für finale abgaben aka Endupload in cis4 student abgabetool - */ - public function postStudentProjektarbeitEndupload() - { - - $projektarbeit_id = $_POST['projektarbeit_id']; - $paabgabe_id = $_POST['paabgabe_id']; - $student_uid = $_POST['student_uid']; - $sprache = $_POST['sprache']; - $abstract = $_POST['abstract']; - $abstract_en = $_POST['abstract_en']; - $schlagwoerter = $_POST['schlagwoerter']; - $schlagwoerter_en = $_POST['schlagwoerter_en']; - $seitenanzahl = $_POST['seitenanzahl']; - $bperson_id = $_POST['bperson_id']; - $paabgabetyp_kurzbz = $_POST['paabgabetyp_kurzbz']; - - if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id) - || !isset($paabgabe_id) || isEmptyString($paabgabe_id) - || !isset($student_uid) || isEmptyString($student_uid) - || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) - $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); - - // TODO: maybe check for other params aswell? - - if ((isset($_FILES) and isset($_FILES['file']) and ! $_FILES['file']['error'])) { - move_uploaded_file($_FILES['file']['tmp_name'], PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'); - - if(file_exists(PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf')) { - - // Loads Libraries - $this->load->library('SignatureLib'); - - // Check if the document is signed - $signaturVorhanden = true; - $signList = SignatureLib::list(PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'); - if (is_array($signList) && count($signList) > 0) - { - // The document is signed - $uploadedDocumentSigned = 'The document is signed'; - } - elseif ($signList === null) - { - $uploadedDocumentSigned = 'WARNING: signature server error'; - } - else - { - $signaturVorhanden = false; - $uploadedDocumentSigned = 'No document signature found'; - } - $this->addMeta('signaturInfo', $uploadedDocumentSigned); - - if ($signaturVorhanden === false) - { - $this->signaturFehltEmail($student_uid); - } - - // TODO error handle get data has data the updates - // update projektarbeit cols - $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); - $this->ProjektarbeitModel->updateProjektarbeit($projektarbeit_id,$sprache,$abstract,$abstract_en - ,$schlagwoerter, $schlagwoerter_en, $seitenanzahl); - - - // update paabgabe datum - $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); - $res = $this->PaabgabeModel->update($paabgabe_id, array( - 'abgabedatum' => date('Y-m-d'), - 'updatevon' => getAuthUID(), - 'updateamum' => date('Y-m-d H:i:s') - )); - - $this->sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid); - - $this->terminateWithSuccess($res); - } else { - $this->terminateWithError('Error moving File'); - } - - } else { - $this->terminateWithError('File missing'); - } - - } - - private function signaturFehltEmail($student_uid) { - - - // Mail an Studiengang wenn keine Signatur gefunden wurde - $student = new student(); - if(!$student->load($student_uid)) - $this->terminateWithError($this->p->t('global','userNichtGefunden'), 'general'); - - $stg_obj = new studiengang(); - if(!$stg_obj->load($student->studiengang_kz)) - $this->terminateWithError($this->p->t('global','fehlerBeimLesenAusDatenbank'), 'general'); - - $subject = 'Abgabe ohne Signatur'; - $tomail = $stg_obj->email; - $data = array( - 'vorname' => $student->vorname, - 'nachname' => $student->nachname, - 'studiengang' => $stg_obj->bezeichnung - ); - - $mailres = sendSanchoMail( - 'ParbeitsbeurteilungSiganturFehlt', - $data, - $tomail, - $subject, - 'sancho_header_min_bw.jpg', - 'sancho_footer_min_bw.jpg' - ); - } - - private function sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid) { - - $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); - - $resBetr = $this->ProjektarbeitModel->getProjektbetreuerAnrede($bperson_id); - - $projektarbeit_obj = new projektarbeit(); - - if(!$projektarbeit_obj->load($projektarbeit_id)) - $this->terminateWithError('Ungueltiger Eintrag'); - - $num_rows_sem = $projektarbeit_obj->projektarbeitIsCurrent($projektarbeit_id); - - if( null === $num_rows_sem || false === $num_rows_sem ) - { - $this->terminateWithError($this->p->t('abgabetool','fehlerAktualitaetProjektarbeit'), 'general'); - } - - foreach($resBetr->retval as $betreuerRow) { - - // query student benutzer view for every betreuer row - $studentUser = $this->ProjektarbeitModel->getProjektarbeitBenutzer($student_uid)->retval[0]; - - // TODO: hasdata, getData etc - - // 1. Begutachter mail ohne Token - $mail_baselink = APP_ROOT."index.ci.php/extensions/FHC-Core-Projektarbeitsbeurteilung/ProjektarbeitsbeurteilungErstbegutachter"; - $mail_fulllink = "$mail_baselink?projektarbeit_id=".$projektarbeit_id."&uid=".$studentUser->uid; - $projekttyp_kurzbz = $projektarbeit_obj->projekttyp_kurzbz; - $subject = $projektarbeit_obj->projekttyp_kurzbz == 'Diplom' ? 'Masterarbeitsbetreuung' : 'Bachelorarbeitsbetreuung'; - $abgabetyp = $paabgabetyp_kurzbz == 'end' ? 'Endabgabe' : 'Zwischenabgabe'; - - $maildata = array(); - $maildata['geehrt'] = "geehrte".($betreuerRow->anrede=="Herr"?"r":""); - $maildata['anrede'] = $betreuerRow->anrede; - $maildata['betreuer_voller_name'] = $betreuerRow->first; - $maildata['student_anrede'] = $studentUser->anrede; - $maildata['student_voller_name'] = trim($studentUser->titelpre." ".$studentUser->vorname." ".$studentUser->nachname." ".$studentUser->titelpost); - $maildata['abgabetyp'] = $abgabetyp; - $maildata['parbeituebersichtlink'] = "

Zur Projektarbeitsübersicht

"; - $maildata['bewertunglink'] = $num_rows_sem >= 1 && $paabgabetyp_kurzbz == 'end' ? "

Zur Beurteilung der Arbeit

" : ""; - $maildata['token'] = ""; - - $mailres = sendSanchoMail( - 'ParbeitsbeurteilungEndupload', - $maildata, - $betreuerRow->mitarbeiter_uid."@".DOMAIN, - $subject, - 'sancho_header_min_bw.jpg', - 'sancho_footer_min_bw.jpg', - get_uid()."@".DOMAIN); - - if(!$mailres) - { - $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailBegutachter'), 'general'); - } - - // 2. Begutachter mail, wenn Endabgabe, mit Token wenn extern - if ($paabgabetyp_kurzbz == 'end') - { - // Zweitbegutachter holen - $zweitbegutachter = new projektbetreuer(); - $zweitbegutachterRes = $zweitbegutachter->getZweitbegutachterWithToken($bperson_id, $projektarbeit_id, $studentUser->uid); - - if ($zweitbegutachterRes) - { - $zweitbegutachterResults = $zweitbegutachter->result; - - foreach ($zweitbegutachterResults as $begutachter) - { - // token generieren, wenn noch nicht vorhanden und notwendig (wird in methode überprüft) - $tokenGenRes = $zweitbegutachter->generateZweitbegutachterToken($begutachter->person_id, $projektarbeit_id); - - if (!$tokenGenRes) - { - $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailZweitBegutachter'), 'general'); - } - - // Zweitbegutachter (evtl. mit Token) holen - $zweitbegutachterMitToken = new projektbetreuer(); - $begutachterMitTokenRes = $zweitbegutachterMitToken->getZweitbegutachterWithToken($bperson_id, $projektarbeit_id, $studentUser->uid, $begutachter->person_id); - - if (!$begutachterMitTokenRes) - { - $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailZweitBegutachter'), 'general'); - } - - // Email an Zweitbegutachter senden - if (isset($zweitbegutachterMitToken->result[0])) - { - $begutachterMitToken = $zweitbegutachterMitToken->result[0]; - - $path = $begutachterMitToken->betreuerart_kurzbz == 'Zweitbegutachter' ? 'ProjektarbeitsbeurteilungZweitbegutachter' : 'ProjektarbeitsbeurteilungErstbegutachter'; - $mail_baselink = APP_ROOT."index.ci.php/extensions/FHC-Core-Projektarbeitsbeurteilung/$path"; - $mail_fulllink = "$mail_baselink?projektarbeit_id=".$projektarbeit_id."&uid=".$studentUser->uid; - $intern = isset($begutachterMitToken->uid); - $mail_link = $intern ? $mail_fulllink : $mail_baselink; - - $zweitbetmaildata = array(); - $zweitbetmaildata['geehrt'] = "geehrte" . ($begutachterMitToken->anrede == "Herr" ? "r" : ""); - $zweitbetmaildata['anrede'] = $begutachterMitToken->anrede; - $zweitbetmaildata['betreuer_voller_name'] = $begutachterMitToken->voller_name; - $zweitbetmaildata['student_anrede'] = $maildata['student_anrede']; - $zweitbetmaildata['student_voller_name'] = $maildata['student_voller_name']; - $zweitbetmaildata['abgabetyp'] = $abgabetyp; - $zweitbetmaildata['parbeituebersichtlink'] = $intern ? $maildata['parbeituebersichtlink'] : ""; - $zweitbetmaildata['bewertunglink'] = $num_rows_sem >= 1 ? "

Zur Beurteilung der Arbeit

" : ""; - $zweitbetmaildata['token'] = $num_rows_sem >= 1 && isset($begutachterMitToken->zugangstoken) && !$intern ? "

Zugangstoken: " . $begutachterMitToken->zugangstoken . "

" : ""; - - $mailres = sendSanchoMail( - 'ParbeitsbeurteilungEndupload', - $zweitbetmaildata, - $begutachterMitToken->email, - $subject, - 'sancho_header_min_bw.jpg', - 'sancho_footer_min_bw.jpg', - get_uid()."@".DOMAIN - ); - - if (!$mailres) - { - $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailBegutachter'), 'general'); - } - } - } - } - } - } - } - - public function getMitarbeiterProjektarbeiten() { - $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); - - $boolParamStr = $this->input->get('showall'); - $trueStrings = ['true', '1']; - $falseStrings = ['false', '0']; - - // Handle missing or invalid parameter - if ($boolParamStr === null) { - $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); - } - $boolParamStrLower = strtolower($boolParamStr); - - if (in_array($boolParamStrLower, $trueStrings, true)) { - $showAllBool = true; - } elseif (in_array($boolParamStrLower, $falseStrings, true)) { - $showAllBool = false; - } else { -// $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); - } - - $projektarbeiten = $this->ProjektarbeitModel->getMitarbeiterProjektarbeiten(getAuthUID(), $showAllBool); - - $this->terminateWithSuccess(array($projektarbeiten, DOMAIN)); - } - - public function postProjektarbeitAbgabe() { - $projektarbeit_id = $_POST['projektarbeit_id']; - $paabgabe_id = $_POST['paabgabe_id']; - $paabgabetyp_kurzbz = $_POST['paabgabetyp_kurzbz']; - $datum = $_POST['datum']; - $fixtermin = $_POST['fixtermin']; - $kurzbz = $_POST['kurzbz']; - - if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id) - || !isset($paabgabe_id) || isEmptyString($paabgabe_id) - || !isset($datum) || isEmptyString($datum) - || !isset($datum) || isEmptyString($datum) - || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) - $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); - - $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); - - if($paabgabe_id == -1) { - $result = $this->PaabgabeModel->insert( - array( - 'projektarbeit_id' => $projektarbeit_id, - 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, - 'fixtermin' => $fixtermin, - 'datum' => $datum, - 'kurzbz' => $kurzbz, - 'insertvon' => getAuthUID(), - 'insertamum' => date('Y-m-d H:i:s') - ) - ); - - $this->terminateWithSuccess($result); - } else { - $result = $this->PaabgabeModel->update( - $paabgabe_id, - array( - 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, - 'datum' => $datum, - 'kurzbz' => $kurzbz, - 'updatevon' => getAuthUID(), - 'updateamum' => date('Y-m-d H:i:s') - ) - ); - - $this->terminateWithSuccess($result); - } - } - - public function deleteProjektarbeitAbgabe() { - $paabgabe_id = $_POST['paabgabe_id']; - - if (!isset($paabgabe_id) || isEmptyString($paabgabe_id)) - $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); - - $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); - - $result = $this->PaabgabeModel->load($paabgabe_id); - $result = $this->getDataOrTerminateWithError($result); - - if(count($result) == 0) - $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); - - // TODO: berechtigung? - if($result[0]->insertvon === getAuthUID()) { - $result = $this->PaabgabeModel->delete($paabgabe_id); - $result = $this->getDataOrTerminateWithError($result); - $this->terminateWithSuccess($result); - } - - $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( - 'neuerAbgabetermin', - $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/Paabgabetyp_model.php b/application/models/education/Paabgabetyp_model.php index b672a3f0e..fce46b3a0 100644 --- a/application/models/education/Paabgabetyp_model.php +++ b/application/models/education/Paabgabetyp_model.php @@ -11,4 +11,10 @@ class Paabgabetyp_model extends DB_Model $this->dbTable = 'campus.tbl_paabgabetyp'; $this->pk = 'paabgabetyp_kurzbz'; } + + public function getAll() { + $qry = "SELECT * FROM campus.tbl_paabgabetyp"; + + return $this->execReadOnlyQuery($qry); + } } diff --git a/public/js/api/factory/abgabe.js b/public/js/api/factory/abgabe.js new file mode 100644 index 000000000..15c7dee43 --- /dev/null +++ b/public/js/api/factory/abgabe.js @@ -0,0 +1,96 @@ +export default { + getStudentProjektarbeiten(uid) { + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getStudentProjektarbeiten', + params: { uid } + }; + }, + getStudentProjektabgaben(detail) { + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getStudentProjektabgaben', + params: { projektarbeit_id: detail.projektarbeit_id, student_uid: detail.student_uid } + }; + }, + postStudentProjektarbeitEndupload(formData) { + return { + method: 'post', + url: '/api/frontend/v1/Abgabe/postStudentProjektarbeitEndupload', + params: { formData }, + config: {Headers: { "Content-Type": "multipart/form-data" }} + }; + + // const url = '/api/frontend/v1/Lehre/postStudentProjektarbeitEndupload'; + // const headers = {Headers: { "Content-Type": "multipart/form-data" }} + // return this.$fhcApi.post(url, formData, headers) + }, + postStudentProjektarbeitZwischenabgabe(formData) { + return { + method: 'post', + url: '/api/frontend/v1/Abgabe/postStudentProjektarbeitZwischenabgabe', + params: { formData }, + config: {Headers: { "Content-Type": "multipart/form-data" }} + }; + + // const url = '/api/frontend/v1/Lehre/postStudentProjektarbeitZwischenabgabe'; + // const headers = {Headers: { "Content-Type": "multipart/form-data" }} + // return this.$fhcApi.post(url, formData, headers) + }, + getStudentProjektarbeitAbgabeFile(paabgabe_id, student_uid) { + // TODO: check if this is fine with new api scheme + + const url = `/Cis/Abgabetool/getStudentProjektarbeitAbgabeFile?paabgabe_id=${paabgabe_id}&student_uid=${student_uid}`; + + window.location = FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + url + }, + getMitarbeiterProjektarbeiten(all) { + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getMitarbeiterProjektarbeiten', + params: { showall: all } + }; + }, + postProjektarbeitAbgabe(termin) { + return { + method: 'post', + url: '/api/frontend/v1/Abgabe/postProjektarbeitAbgabe', + params: { + paabgabe_id: termin.paabgabe_id, + paabgabetyp_kurzbz: termin.bezeichnung.paabgabetyp_kurzbz, + datum: termin.datum, + fixtermin: termin.fixtermin, + insertvon: termin.insertvon, + kurzbz: termin.kurzbz, + projektarbeit_id: termin.projektarbeit_id + } + }; + }, + deleteProjektarbeitAbgabe(paabgabe_id) { + return { + method: 'post', + url: '/api/frontend/v1/Abgabe/deleteProjektarbeitAbgabe', + params: { paabgabe_id } + }; + }, + postSerientermin(datum, paabgabetyp_kurzbz, bezeichnung, kurzbz, projektarbeit_ids) { + return { + method: 'post', + url: '/api/frontend/v1/Abgabe/postSerientermin', + params: { datum, paabgabetyp_kurzbz, bezeichnung, kurzbz, projektarbeit_ids } + }; + }, + fetchDeadlines(person_id) { + return { + method: 'post', + url: '/api/frontend/v1/Abgabe/fetchDeadlines', + params: { person_id } + }; + }, + getPaAbgabetypen() { + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getPaAbgabetypen' + }; + } +}; \ No newline at end of file diff --git a/public/js/api/lehre.js b/public/js/api/lehre.js index 5797a2c75..cd7129d61 100644 --- a/public/js/api/lehre.js +++ b/public/js/api/lehre.js @@ -18,80 +18,5 @@ export default { `/api/frontend/v1/Lehre/Pruefungen/${lehrveranstaltung_id}` , {} ); - }, - getStudentProjektarbeiten(uid) { - return this.$fhcApi.get( - `/api/frontend/v1/Lehre/getStudentProjektarbeiten/${uid}` - , {} - ); - }, - getStudentProjektabgaben(detail) { - return this.$fhcApi.get( - `/api/frontend/v1/Lehre/getStudentProjektabgaben` - , { - projektarbeit_id: detail.projektarbeit_id, - student_uid: detail.student_uid - } - ); - }, - postStudentProjektarbeitEndupload(formData) { - const url = '/api/frontend/v1/Lehre/postStudentProjektarbeitEndupload'; - const headers = {Headers: { "Content-Type": "multipart/form-data" }} - return this.$fhcApi.post(url, formData, headers) - }, - postStudentProjektarbeitZwischenabgabe(formData) { - const url = '/api/frontend/v1/Lehre/postStudentProjektarbeitZwischenabgabe'; - const headers = {Headers: { "Content-Type": "multipart/form-data" }} - return this.$fhcApi.post(url, formData, headers) - }, - getStudentProjektarbeitAbgabeFile(paabgabe_id, student_uid) { - const url = `/Cis/Abgabetool/getStudentProjektarbeitAbgabeFile?paabgabe_id=${paabgabe_id}&student_uid=${student_uid}`; - - window.location = FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + url - }, - getMitarbeiterProjektarbeiten(uid, all) { - return this.$fhcApi.get( - `/api/frontend/v1/Lehre/getMitarbeiterProjektarbeiten?showall=${all}` - , {} - ); - }, - postProjektarbeitAbgabe(termin) { - const payload = { - paabgabe_id: termin.paabgabe_id, - paabgabetyp_kurzbz: termin.bezeichnung.paabgabetyp_kurzbz, - datum: termin.datum, - fixtermin: termin.fixtermin, - insertvon: termin.insertvon, - kurzbz: termin.kurzbz, - projektarbeit_id: termin.projektarbeit_id - } - const url = '/api/frontend/v1/Lehre/postProjektarbeitAbgabe'; - - return this.$fhcApi.post(url, payload, null) - - }, - deleteProjektarbeitAbgabe(paabgabe_id) { - const payload = { - paabgabe_id - } - 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/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js index 0900282ef..70b86e60f 100644 --- a/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js +++ b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js @@ -55,7 +55,7 @@ export const AbgabeMitarbeiterDetail = { }, saveTermin(termin) { const paabgabe_id = termin.paabgabe_id - this.$fhcApi.factory.lehre.postProjektarbeitAbgabe(termin).then( (res) => { + this.$api.call(ApiAbgabe.postProjektarbeitAbgabe(termin)).then( (res) => { if(res?.meta?.status == 'success') { this.$fhcAlert.alertSuccess(this.$p.t('ui/gespeichert')) @@ -86,7 +86,7 @@ export const AbgabeMitarbeiterDetail = { }) }, deleteTermin(termin) { - this.$fhcApi.factory.lehre.deleteProjektarbeitAbgabe(termin.paabgabe_id).then( (res) => { + this.$api.call(ApiAbgabe.deleteProjektarbeitAbgabe(termin.paabgabe_id)).then( (res) => { if(res?.meta?.status == 'success') { this.$fhcAlert.alertSuccess(this.$p.t('ui/genericDeleted', [this.$p.t('abgabetool/abgabe')])) // this.$p.t('global/tooltipLektorDeleteKontrolle', [this.$entryParams.permissions.kontrolleDeleteMaxReach ]) @@ -108,7 +108,9 @@ export const AbgabeMitarbeiterDetail = { return true; }, downloadAbgabe(termin) { - this.$fhcApi.factory.lehre.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid) + // TODO: test + this.$api.call(ApiAbgabe.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid)) + // this.$fhcApi.factory.lehre.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid) }, dateDiffInDays(datum, today){ const oneDayMs = 1000 * 60 * 60 * 24 diff --git a/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js b/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js index 1eb5d099c..107138962 100644 --- a/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js +++ b/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js @@ -74,7 +74,7 @@ export const AbgabeStudentDetail = { for (let i = 0; i < this.enduploadTermin.file.length; i++) { formData.append('file', this.enduploadTermin.file[i]); } - this.$fhcApi.factory.lehre.postStudentProjektarbeitEndupload(formData) + this.$api.call(ApiAbgabe.postStudentProjektarbeitEndupload(formData)) .then(res => { this.handleUploadRes(res) }) @@ -82,7 +82,9 @@ export const AbgabeStudentDetail = { this.$refs.modalContainerEnduploadZusatzdaten.hide() }, downloadAbgabe(termin) { - this.$fhcApi.factory.lehre.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid) + // TODO: test + this.$api.call(ApiAbgabe.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid)) + // this.$fhcApi.factory.lehre.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid) }, formatDate(dateParam) { const date = new Date(dateParam) @@ -117,7 +119,8 @@ export const AbgabeStudentDetail = { for (let i = 0; i < termin.file.length; i++) { formData.append('file', termin.file[i]); } - this.$fhcApi.factory.lehre.postStudentProjektarbeitZwischenabgabe(formData) + + this.$api.call(ApiAbgabe.postStudentProjektarbeitZwischenabgabe(formData)) .then(res => { this.handleUploadRes(res) }) diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js b/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js index 341d61920..a102e6e28 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js @@ -3,6 +3,7 @@ import AbgabeDetail from "./AbgabeMitarbeiterDetail.js"; import VerticalSplit from "../../verticalsplit/verticalsplit.js" import BsModal from '../../Bootstrap/Modal.js'; import VueDatePicker from '../../vueDatepicker.js.php'; +import ApiAbgabe from '../../../api/abgabe.js' export const AbgabetoolMitarbeiter = { name: "AbgabetoolMitarbeiter", @@ -176,13 +177,13 @@ export const AbgabetoolMitarbeiter = { }, addSeries() { this.saving = true - this.$fhcApi.factory.lehre.postSerientermin( + this.$api.call(ApiAbgabe.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 => { + )).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? @@ -321,7 +322,7 @@ export const AbgabetoolMitarbeiter = { this.$refs.abgabeTable.tabulator.setData(d); }, loadProjektarbeiten(all = false, callback) { - this.$fhcApi.factory.lehre.getMitarbeiterProjektarbeiten(this.viewData?.uid ?? null, all) + this.$api.call(ApiAbgabe.getMitarbeiterProjektarbeiten(all)) .then(res => { if(res?.data) this.setupData(res.data) }).finally(() => { @@ -332,7 +333,7 @@ export const AbgabetoolMitarbeiter = { }, loadAbgaben(details) { return new Promise((resolve) => { - this.$fhcApi.factory.lehre.getStudentProjektabgaben(details) + this.$api.call(ApiAbgabe.getStudentProjektabgaben(details)) .then(res => { resolve(res) }) @@ -369,7 +370,13 @@ export const AbgabetoolMitarbeiter = { }, created() { - + // fetch abgabetypen options + this.$api.call(ApiAbgabe.getPaAbgabetypen()).then(res => { + this.paabgabetypOptions = res.data + this.tabulatorCanBeBuilt = true // because promises would be more work and not much better here + }).catch(e => { + this.loading = false + }) }, mounted() { this.setupMounted() diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js b/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js index d1eab7c6e..3890f2764 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js @@ -186,14 +186,14 @@ export const AbgabetoolStudent = { this.$refs.abgabeTable.tabulator.setData(d); }, loadProjektarbeiten() { - this.$fhcApi.factory.lehre.getStudentProjektarbeiten(this.student_uid_prop || this.viewData?.uid || null) + this.$api.call(ApiAbgabe.getStudentProjektarbeiten(this.student_uid_prop || this.viewData?.uid || null)) .then(res => { if(res?.data) this.setupData(res.data) }) }, loadAbgaben(details) { return new Promise((resolve) => { - this.$fhcApi.factory.lehre.getStudentProjektabgaben(details) + this.$api.call(ApiAbgabe.getStudentProjektabgaben(details)) .then(res => { resolve(res) }) diff --git a/public/js/components/Cis/Abgabetool/DeadlineOverview.js b/public/js/components/Cis/Abgabetool/DeadlineOverview.js index d2b133979..67f692f84 100644 --- a/public/js/components/Cis/Abgabetool/DeadlineOverview.js +++ b/public/js/components/Cis/Abgabetool/DeadlineOverview.js @@ -84,7 +84,7 @@ export const DeadlineOverview = { this.tableBuiltResolve = resolve }, loadDeadlines() { - this.$fhcApi.factory.lehre.fetchDeadlines(this.person_uid_prop ?? null) + this.$api.call(ApiAbgabe.fetchDeadlines(this.person_uid_prop ?? null)) .then(res => { if(res?.data) this.setupData(res.data) }) diff --git a/system/dbupdate_3.4/61164_abgabetool_quality_gates.php b/system/dbupdate_3.4/61164_abgabetool_quality_gates.php new file mode 100644 index 000000000..1341b3c5f --- /dev/null +++ b/system/dbupdate_3.4/61164_abgabetool_quality_gates.php @@ -0,0 +1,29 @@ +db_query("SELECT 1 FROM campus.tbl_paabgabetyp WHERE paabgabetyp_kurzbz='qualgate1'")) +{ + if($db->db_num_rows($result) === 0) + { + $qry = "INSERT INTO campus.tbl_paabgabetyp (paabgabetyp_kurzbz, bezeichnung) VALUES('qualgate1', 'Quality Gate 1');"; + + if(!$db->db_query($qry)) + echo 'campus.tbl_paabgabetyp: '.$db->db_last_error().'
'; + else + echo '
paabgabetyp quality gate 1 hinzugefuegt'; + } +} + +if($result = $db->db_query("SELECT 1 FROM campus.tbl_paabgabetyp WHERE paabgabetyp_kurzbz='qualgate2'")) +{ + if($db->db_num_rows($result) === 0) + { + $qry = "INSERT INTO campus.tbl_paabgabetyp (paabgabetyp_kurzbz, bezeichnung) VALUES('qualgate2', 'Quality Gate 2');"; + + if(!$db->db_query($qry)) + echo 'campus.tbl_paabgabetyp: '.$db->db_last_error().'
'; + else + echo '
paabgabetyp quality gate 2 hinzugefuegt'; + } +} From 63390b192c0b81ebbd415e54e7c90a0d31702f31 Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Tue, 26 Aug 2025 17:15:37 +0200 Subject: [PATCH 009/185] qualgate 1&2 dbupdate script, note fkey reference & upload required flag in paabgabe; noten api duplicate from notentool for now; WIP more emails; qualgates benotbar & saveable aswell as upload flag; --- .../controllers/api/frontend/v1/Abgabe.php | 105 +++++++++++++++--- application/models/education/Note_model.php | 8 ++ .../models/education/Projektarbeit_model.php | 2 + .../education/Projektbetreuer_model.php | 36 ++++++ public/js/api/factory/abgabe.js | 23 ++-- .../Cis/Abgabetool/AbgabeMitarbeiterDetail.js | 70 ++++++------ .../Cis/Abgabetool/AbgabeStudentDetail.js | 5 +- .../Cis/Abgabetool/AbgabetoolMitarbeiter.js | 56 +++++----- .../Cis/Abgabetool/AbgabetoolStudent.js | 9 +- .../Cis/Abgabetool/DeadlineOverview.js | 1 + public/js/plugins/Api.js | 1 + .../61164_abgabetool_quality_gates.php | 33 ++++++ 12 files changed, 256 insertions(+), 93 deletions(-) diff --git a/application/controllers/api/frontend/v1/Abgabe.php b/application/controllers/api/frontend/v1/Abgabe.php index 61a3b4c44..86f248c84 100644 --- a/application/controllers/api/frontend/v1/Abgabe.php +++ b/application/controllers/api/frontend/v1/Abgabe.php @@ -27,7 +27,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); //require_once('../../../include/projektarbeit.class.php'); //require_once('../../../include/projektbetreuer.class.php'); -class Lehre extends FHCAPI_Controller +class Abgabe extends FHCAPI_Controller { /** @@ -45,7 +45,8 @@ class Lehre extends FHCAPI_Controller 'deleteProjektarbeitAbgabe' => self::PERM_LOGGED, 'postSerientermin' => self::PERM_LOGGED, 'fetchDeadlines' => self::PERM_LOGGED, // TODO: mitarbeiter recht prüfen - 'getPaAbgabetypen' => self::PERM_LOGGED + 'getPaAbgabetypen' => self::PERM_LOGGED, + 'getNoten' => self::PERM_LOGGED ]); $this->load->library('PhrasesLib'); @@ -100,8 +101,10 @@ class Lehre extends FHCAPI_Controller /** * fetches all projektarbeiten and betreuer for a given student_uid used in cis4 student abgabetool */ - public function getStudentProjektarbeiten($uid) + public function getStudentProjektarbeiten() { + $uid = $this->input->get("uid",TRUE); + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); @@ -254,8 +257,7 @@ class Lehre extends FHCAPI_Controller } private function signaturFehltEmail($student_uid) { - - + // Mail an Studiengang wenn keine Signatur gefunden wurde $student = new student(); if(!$student->load($student_uid)) @@ -326,6 +328,10 @@ class Lehre extends FHCAPI_Controller $maildata['bewertunglink'] = $num_rows_sem >= 1 && $paabgabetyp_kurzbz == 'end' ? "

Zur Beurteilung der Arbeit

" : ""; $maildata['token'] = ""; + // TODO: clarify if all betreuer are mitarbeiter and have benutzer entries + // or if uid = null has to be checked WITH + // 'CASE WHEN tbl_benutzer.uid IS NULL THEN kontakt ELSE tbl_benutzer.uid || '@".DOMAIN."' END AS email' + $email = $this->getBetreuerEmail($bperson_id); if(!$email) $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailBegutachter'), 'general'); @@ -334,7 +340,6 @@ class Lehre extends FHCAPI_Controller 'ParbeitsbeurteilungEndupload', $maildata, $email, -// $betreuerRow->mitarbeiter_uid."@".DOMAIN, $subject, 'sancho_header_min_bw.jpg', 'sancho_footer_min_bw.jpg', @@ -397,6 +402,12 @@ class Lehre extends FHCAPI_Controller $zweitbetmaildata['bewertunglink'] = $num_rows_sem >= 1 ? "

Zur Beurteilung der Arbeit

" : ""; $zweitbetmaildata['token'] = $num_rows_sem >= 1 && isset($begutachterMitToken->zugangstoken) && !$intern ? "

Zugangstoken: " . $begutachterMitToken->zugangstoken . "

" : ""; + + $email = $this->getBetreuerEmail($bperson_id); + + if(!$email) $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailBegutachter'), 'general'); + + $mailres = sendSanchoMail( 'ParbeitsbeurteilungEndupload', $zweitbetmaildata, @@ -443,7 +454,8 @@ class Lehre extends FHCAPI_Controller $this->terminateWithSuccess(array($projektarbeiten, DOMAIN)); } - + + // called by abgabetool/mitarbeiter when adding a new termin public function postProjektarbeitAbgabe() { $projektarbeit_id = $_POST['projektarbeit_id']; $paabgabe_id = $_POST['paabgabe_id']; @@ -451,6 +463,8 @@ class Lehre extends FHCAPI_Controller $datum = $_POST['datum']; $fixtermin = $_POST['fixtermin']; $kurzbz = $_POST['kurzbz']; + $note = $_POST['note']; + $upload_required = $_POST['upload_required']; if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id) || !isset($paabgabe_id) || isEmptyString($paabgabe_id) @@ -469,12 +483,14 @@ class Lehre extends FHCAPI_Controller 'fixtermin' => $fixtermin, 'datum' => $datum, 'kurzbz' => $kurzbz, + 'note' => $note, + 'upload_required' => $upload_required, 'insertvon' => getAuthUID(), 'insertamum' => date('Y-m-d H:i:s') ) ); - $this->terminateWithSuccess($result); + } else { $result = $this->PaabgabeModel->update( $paabgabe_id, @@ -482,13 +498,25 @@ class Lehre extends FHCAPI_Controller 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, 'datum' => $datum, 'kurzbz' => $kurzbz, + 'note' => $note, + 'upload_required' => $upload_required, 'updatevon' => getAuthUID(), 'updateamum' => date('Y-m-d H:i:s') ) ); - - $this->terminateWithSuccess($result); + } + + $paabgabe_id = $this->getDataOrTerminateWithError($result); + + $paabgabe = $this->PaabgabeModel->load($paabgabe_id); + + // check if $paaabgabe is a qual gate and its note is deemed negative + // -> send email to student with that info + + // TODO: DEFAULT NOTE 9 OR DEFAULT NOTE NULL? 9 COUNTS AS NEGATIV :/ + + $this->terminateWithSuccess($result); } public function deleteProjektarbeitAbgabe() { @@ -631,17 +659,58 @@ class Lehre extends FHCAPI_Controller $result = $this->PaabgabetypModel->getAll(); $paabgabetypen = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($paabgabetypen); } private function getBetreuerEmail($person_id) { - // check if betreuer is intern (fixangestellt = true) - // -> email: uid@DOMAIN - - // if betreuer is extern, check if there are private email contacts - // in tbl_kontakt. if so, return them - - return null; + $this->load->model('education/Projektbetreuer_model', 'ProjektbetreuerModel'); + $result = $this->ProjektbetreuerModel->getBetreuerEmail($person_id); + $email = $this->getDataOrTerminateWithError($result); + return $email[0]->email; } -} + //TODO: SWITCH TO NOTEN API ONCE NOTENTOOL IS IN MASTER TO AVOID DUPLICATE API + + /** + * GET METHOD + * returns List of all available & active NotenOptions + */ + public function getNoten() { + $this->load->model('education/Note_model', 'NoteModel'); + + $result = $this->NoteModel->getAllActive(); + $noten = $this->getDataOrTerminateWithError($result); + $this->terminateWithSuccess($noten); + } + + private function sendQualGateNegativEmail($student_uid) { + // Mail an Student wenn Qualgate negativ beurteilt wurde + $student = new student(); + if(!$student->load($student_uid)) + $this->terminateWithError($this->p->t('global','userNichtGefunden'), 'general'); + + // TODO: frasen + $subject = 'Quality Gate Negativ'; + $tomail = $student_uid.'@'.DOMAIN; + + + // TODO: emaildata + $data = array( + 'betreuerfullname' => $student->vorname, + 'qualgatebezeichnung' => $student->nachname, + 'datum' => $datum, + 'projektarbeitname' => $name + ); + + $mailres = sendSanchoMail( + 'QualGateNegativ', + $data, + $tomail, + $subject + ); + + return $mailres; + } +} \ No newline at end of file diff --git a/application/models/education/Note_model.php b/application/models/education/Note_model.php index 80b454398..87a1501e0 100644 --- a/application/models/education/Note_model.php +++ b/application/models/education/Note_model.php @@ -11,4 +11,12 @@ class Note_model extends DB_Model $this->dbTable = 'lehre.tbl_note'; $this->pk = 'note'; } + + public function getAllActive() { + $qry ="SELECT * + FROM lehre.tbl_note + WHERE aktiv = true"; + + return $this->execReadOnlyQuery($qry); + } } \ No newline at end of file diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index 4083dbf6e..b1971cea7 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -167,6 +167,8 @@ class Projektarbeit_model extends DB_Model campus.tbl_paabgabe.fixtermin, campus.tbl_paabgabe.kurzbz, campus.tbl_paabgabe.datum, + campus.tbl_paabgabe.note, + campus.tbl_paabgabe.upload_required, campus.tbl_paabgabetyp.paabgabetyp_kurzbz, campus.tbl_paabgabetyp.bezeichnung, campus.tbl_paabgabe.abgabedatum, diff --git a/application/models/education/Projektbetreuer_model.php b/application/models/education/Projektbetreuer_model.php index 95950bf95..ae78b96d9 100644 --- a/application/models/education/Projektbetreuer_model.php +++ b/application/models/education/Projektbetreuer_model.php @@ -231,4 +231,40 @@ class Projektbetreuer_model extends DB_Model return $this->execQuery($qry, array($projektarbeit_id, $betreuer_person_id)); } + + /** + * Gets email of a Betreuer for a Projektarbeit. + * Projektarbeitbetreuer can be external employees, which should be contacted on their private + * email contact, if they have one. Internal Betreuer should be contacted on their "uid@DOMAIN" adress. + * @param int betreuer_person_id + * @return object success or error + */ + public function getBetreuerEmail($betreuer_person_id) { + // TODO: check if benutzer uid exists, not fixangestellt + + $qry =" + SELECT uid, + CASE + WHEN public.tbl_mitarbeiter.fixangestellt = false + THEN ( + SELECT kontakt AS email + FROM public.tbl_kontakt + WHERE + public.tbl_kontakt.person_id = ? AND + kontakttyp = 'email' + ) + + ELSE ( + SELECT public.tbl_benutzer.uid || '@' || '".DOMAIN."' AS email + FROM public.tbl_benutzer + WHERE person_id = ? + ) + END AS email + FROM public.tbl_benutzer + JOIN public.tbl_mitarbeiter ON (public.tbl_benutzer.uid = public.tbl_mitarbeiter.mitarbeiter_uid) + WHERE person_id = ? + "; + + return $this->execReadOnlyQuery($qry, array($betreuer_person_id, $betreuer_person_id, $betreuer_person_id)); + } } diff --git a/public/js/api/factory/abgabe.js b/public/js/api/factory/abgabe.js index 15c7dee43..0602a218c 100644 --- a/public/js/api/factory/abgabe.js +++ b/public/js/api/factory/abgabe.js @@ -17,25 +17,17 @@ export default { return { method: 'post', url: '/api/frontend/v1/Abgabe/postStudentProjektarbeitEndupload', - params: { formData }, + params: formData, config: {Headers: { "Content-Type": "multipart/form-data" }} }; - - // const url = '/api/frontend/v1/Lehre/postStudentProjektarbeitEndupload'; - // const headers = {Headers: { "Content-Type": "multipart/form-data" }} - // return this.$fhcApi.post(url, formData, headers) }, postStudentProjektarbeitZwischenabgabe(formData) { return { method: 'post', url: '/api/frontend/v1/Abgabe/postStudentProjektarbeitZwischenabgabe', - params: { formData }, + params: formData, config: {Headers: { "Content-Type": "multipart/form-data" }} }; - - // const url = '/api/frontend/v1/Lehre/postStudentProjektarbeitZwischenabgabe'; - // const headers = {Headers: { "Content-Type": "multipart/form-data" }} - // return this.$fhcApi.post(url, formData, headers) }, getStudentProjektarbeitAbgabeFile(paabgabe_id, student_uid) { // TODO: check if this is fine with new api scheme @@ -59,6 +51,8 @@ export default { paabgabe_id: termin.paabgabe_id, paabgabetyp_kurzbz: termin.bezeichnung.paabgabetyp_kurzbz, datum: termin.datum, + note: termin.note, + upload_required: termin.upload_required, fixtermin: termin.fixtermin, insertvon: termin.insertvon, kurzbz: termin.kurzbz, @@ -92,5 +86,12 @@ export default { method: 'get', url: '/api/frontend/v1/Abgabe/getPaAbgabetypen' }; - } + }, + //TODO: SWITCH TO NOTEN API ONCE NOTENTOOL IS IN MASTER TO AVOID DUPLICATE API + getNoten(){ + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getNoten' + }; + }, }; \ No newline at end of file diff --git a/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js index 70b86e60f..c70c40ba7 100644 --- a/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js +++ b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js @@ -1,5 +1,6 @@ import BsModal from '../../Bootstrap/Modal.js'; import VueDatePicker from '../../vueDatepicker.js.php'; +import ApiAbgabe from '../../../api/factory/abgabe.js' const today = new Date() export const AbgabeMitarbeiterDetail = { @@ -12,6 +13,7 @@ export const AbgabeMitarbeiterDetail = { Textarea: primevue.textarea, VueDatePicker }, + inject: ['abgabeTypeOptions', 'allowedNotenOptions'], props: { projektarbeit: { type: Object, @@ -23,30 +25,7 @@ export const AbgabeMitarbeiterDetail = { 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, - // 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' - } - ] + allActiveLanguages: FHC_JS_DATA_STORAGE_OBJECT.server_languages } }, methods: { @@ -55,6 +34,9 @@ export const AbgabeMitarbeiterDetail = { }, saveTermin(termin) { const paabgabe_id = termin.paabgabe_id + // 9 => magic number for "noch nicht eingetragen" + termin.note = termin.note?.note ?? 9 + this.$api.call(ApiAbgabe.postProjektarbeitAbgabe(termin)).then( (res) => { if(res?.meta?.status == 'success') { this.$fhcAlert.alertSuccess(this.$p.t('ui/gespeichert')) @@ -69,8 +51,10 @@ export const AbgabeMitarbeiterDetail = { 'fixtermin': false, 'kurzbz': '', 'datum': new Date().toISOString().split('T')[0], - 'paabgabetyp_kurzbz': '', - 'bezeichnung': '', + 'paabgabetyp_kurzbz': termin.paabgabetyp_kurzbz, + 'note': this.allowedNotenOptions.find(opt => opt.note == termin.note?.note), + 'upload_required': termin.upload_required, + 'bezeichnung': this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz === termin.paabgabetyp_kurzbz), 'abgabedatum': null, 'insertvon': this.viewData?.uid ?? '', 'allowedToSave': true, @@ -149,6 +133,9 @@ export const AbgabeMitarbeiterDetail = { getOptionLabelAbgabetyp(option){ return option.bezeichnung }, + getNotenOptionLabel(option) { + return option.bezeichnung + }, formatDate(dateParam) { const date = new Date(dateParam) // handle missing leading 0 @@ -200,10 +187,8 @@ export const AbgabeMitarbeiterDetail = { template: `
-
{{$p.t('abgabetool/c4abgabeMitarbeiterbereich')}}
-

{{projektarbeit?.student}}

@@ -248,7 +233,9 @@ export const AbgabeMitarbeiterDetail = {
{{$p.t('abgabetool/c4fixtermin')}}
{{$p.t('abgabetool/c4zieldatum')}}
{{$p.t('abgabetool/c4abgabetyp')}}
-
{{$p.t('abgabetool/c4abgabekurzbz')}}
+
{{$p.t('abgabetool/c4note')}}
+
{{$p.t('abgabetool/c4upload_required')}}
+
{{$p.t('abgabetool/c4abgabekurzbz')}}
{{$p.t('abgabetool/c4abgabedatum')}}
@@ -278,12 +265,30 @@ export const AbgabeMitarbeiterDetail = { :style="{'width': '100%'}" :disabled="!termin.allowedToSave" v-model="termin.bezeichnung" - :options="allAbgabeTypes" + :options="abgabeTypeOptions" :optionLabel="getOptionLabelAbgabetyp">
-
- +
+ + +
+
+ + +
+
+
{{ termin.abgabedatum?.split("-").reverse().join(".") }} @@ -310,7 +315,6 @@ export const AbgabeMitarbeiterDetail = {
- `, }; diff --git a/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js b/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js index 107138962..3271ed97f 100644 --- a/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js +++ b/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js @@ -1,6 +1,7 @@ import Upload from '../../../components/Form/Upload/Dms.js'; import BsModal from '../../Bootstrap/Modal.js'; import VueDatePicker from '../../vueDatepicker.js.php'; +import ApiAbgabe from '../../../api/factory/abgabe.js' const today = new Date() export const AbgabeStudentDetail = { @@ -198,7 +199,7 @@ export const AbgabeStudentDetail = { getEid() { return this.$p.t('abgabetool/c4eidesstattlicheErklaerung') }, - getEnduploadErlaubt() { + getAllowedToSendEndupload() { return !this.eidAkzeptiert } }, @@ -371,7 +372,7 @@ export const AbgabeStudentDetail = { diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js b/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js index a102e6e28..c16abc8a3 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js @@ -3,7 +3,7 @@ import AbgabeDetail from "./AbgabeMitarbeiterDetail.js"; import VerticalSplit from "../../verticalsplit/verticalsplit.js" import BsModal from '../../Bootstrap/Modal.js'; import VueDatePicker from '../../vueDatepicker.js.php'; -import ApiAbgabe from '../../../api/abgabe.js' +import ApiAbgabe from '../../../api/factory/abgabe.js' export const AbgabetoolMitarbeiter = { name: "AbgabetoolMitarbeiter", @@ -16,6 +16,12 @@ export const AbgabetoolMitarbeiter = { Textarea: primevue.textarea, VueDatePicker }, + provide() { + return { + abgabeTypeOptions: Vue.computed(() => this.abgabeTypeOptions), + allowedNotenOptions: Vue.computed(() => this.allowedNotenOptions) + } + }, props: { viewData: { type: Object, @@ -30,29 +36,9 @@ export const AbgabetoolMitarbeiter = { 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' - } - ], + abgabeTypeOptions: null, + notenOptions: null, + allowedNotenOptions: null, serienTermin: Vue.reactive({ datum: new Date(), bezeichnung: { @@ -222,6 +208,8 @@ export const AbgabetoolMitarbeiter = { 'fixtermin': false, 'kurzbz': '', 'datum': new Date().toISOString().split('T')[0], + 'note': this.allowedNotenOptions.find(opt => opt.note == 9), + 'upload_required': false, 'paabgabetyp_kurzbz': '', 'bezeichnung': '', 'abgabedatum': null, @@ -229,6 +217,7 @@ export const AbgabetoolMitarbeiter = { }) pa.abgabetermine.forEach(termin => { + termin.note = this.allowedNotenOptions.find(opt => opt.note == termin.note) termin.file = [] termin.allowedToSave = termin.insertvon == this.viewData?.uid && pa.betreuerart_kurzbz != 'Zweitbegutachter' termin.allowedToDelete = termin.allowedToSave && !termin.abgabedatum @@ -370,10 +359,23 @@ export const AbgabetoolMitarbeiter = { }, created() { + // fetch noten options + //TODO: SWITCH TO NOTEN API ONCE NOTENTOOL IS IN MASTER TO AVOID DUPLICATE API + this.$api.call(ApiAbgabe.getNoten()).then(res => { + this.notenOptions = res.data + // TODO: more sophisticated way to filter for these two, in essence it is still hardcoded + this.allowedNotenOptions = this.notenOptions.filter( + opt => opt.bezeichnung === 'Bestanden' + || opt.bezeichnung === 'Nicht bestanden' + || opt.bezeichnung === 'Noch nicht eingetragen' + ) + }).catch(e => { + this.loading = false + }) + // fetch abgabetypen options this.$api.call(ApiAbgabe.getPaAbgabetypen()).then(res => { - this.paabgabetypOptions = res.data - this.tabulatorCanBeBuilt = true // because promises would be more work and not much better here + this.abgabeTypeOptions = res.data }).catch(e => { this.loading = false }) @@ -419,7 +421,7 @@ export const AbgabetoolMitarbeiter = {
diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js b/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js index 3890f2764..bfd5da01b 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js @@ -1,6 +1,7 @@ import {CoreFilterCmpt} from "../../../components/filter/Filter.js"; import AbgabeDetail from "./AbgabeStudentDetail.js"; import VerticalSplit from "../../verticalsplit/verticalsplit.js"; +import ApiAbgabe from '../../../api/factory/abgabe.js' export const AbgabetoolStudent = { name: "AbgabetoolStudent", @@ -82,6 +83,9 @@ export const AbgabetoolStudent = { ]}; }, methods: { + checkQualityGates(termine, enduploadtermin) { + return true + }, isPastDate(date) { return new Date(date) < new Date(Date.now()) }, @@ -91,10 +95,11 @@ export const AbgabetoolStudent = { pa.abgabetermine = res.data[0].retval pa.abgabetermine.forEach(termin => { termin.file = [] - termin.allowedToUpload = true + // termin.allowedToUpload = true // TODO: fixtermin logic? - if(termin.bezeichnung == 'Endupload' && this.isPastDate(termin.datum)) { + if(termin.bezeichnung == 'Endupload' && + (this.isPastDate(termin.datum) || this.checkQualityGates(pa.abgabetermine, termin))) { // termin.allowedToUpload = false } else { diff --git a/public/js/components/Cis/Abgabetool/DeadlineOverview.js b/public/js/components/Cis/Abgabetool/DeadlineOverview.js index 67f692f84..6f8347169 100644 --- a/public/js/components/Cis/Abgabetool/DeadlineOverview.js +++ b/public/js/components/Cis/Abgabetool/DeadlineOverview.js @@ -1,4 +1,5 @@ import {CoreFilterCmpt} from "../../../components/filter/Filter.js"; +import ApiAbgabe from '../../../api/factory/abgabe.js' export const DeadlineOverview = { name: "DeadlineOverview", diff --git a/public/js/plugins/Api.js b/public/js/plugins/Api.js index 43c2b3064..e3e604d6c 100644 --- a/public/js/plugins/Api.js +++ b/public/js/plugins/Api.js @@ -164,6 +164,7 @@ export default { return fhcApiAxios.post(uri, data, config); }, call(factory, configoverwrite, form) { + debugger if (Array.isArray(factory)) { const $fhcAlert = app.config.globalProperties.$fhcAlert; const $api = app.config.globalProperties.$api; diff --git a/system/dbupdate_3.4/61164_abgabetool_quality_gates.php b/system/dbupdate_3.4/61164_abgabetool_quality_gates.php index 1341b3c5f..b4f6fd7c9 100644 --- a/system/dbupdate_3.4/61164_abgabetool_quality_gates.php +++ b/system/dbupdate_3.4/61164_abgabetool_quality_gates.php @@ -27,3 +27,36 @@ if($result = $db->db_query("SELECT 1 FROM campus.tbl_paabgabetyp WHERE paabgabet echo '
paabgabetyp quality gate 2 hinzugefuegt'; } } + +if($result = $db->db_query("SELECT 1 FROM information_schema.columns WHERE table_schema = 'campus' AND table_name = 'tbl_paabgabe' AND column_name = 'note'")) +{ + if($db->db_num_rows($result) === 0) + { + + $qry = "ALTER TABLE campus.tbl_paabgabe + ADD COLUMN note SMALLINT NOT NULL DEFAULT 9, + ADD CONSTRAINT tbl_paabgabe_note_fkey + FOREIGN KEY (note) + REFERENCES lehre.tbl_note(note) + ON UPDATE CASCADE ON DELETE RESTRICT;"; + + if(!$db->db_query($qry)) + echo 'campus.tbl_paabgabe: '.$db->db_last_error().'
'; + else + echo '
paabgabe column note default 9 (noch nicht eingetragen) hinzugefuegt'; + } +} + +if($result = $db->db_query("SELECT 1 FROM information_schema.columns WHERE table_schema = 'campus' AND table_name = 'tbl_paabgabe' AND column_name = 'upload_required'")) +{ + if($db->db_num_rows($result) === 0) + { + $qry = "ALTER TABLE campus.tbl_paabgabe + ADD COLUMN IF NOT EXISTS upload_required boolean DEFAULT false;"; + + if(!$db->db_query($qry)) + echo 'campus.tbl_paabgabe: '.$db->db_last_error().'
'; + else + echo '
paabgabe column upload_required default false hinzugefuegt'; + } +} \ No newline at end of file From 1f0fe08b696a1d265ae2c93991456c883c3625ec Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Fri, 29 Aug 2025 14:15:20 +0200 Subject: [PATCH 010/185] upload_required => allowed; hardcoded links => config; styling; endupload/qualgate logic; phrasen; --- application/config/abgabe.php | 9 + .../controllers/api/frontend/v1/Abgabe.php | 121 +++++++--- .../models/education/Projektarbeit_model.php | 25 +- .../education/Projektbetreuer_model.php | 36 --- public/js/api/factory/abgabe.js | 13 +- .../Cis/Abgabetool/AbgabeMitarbeiterDetail.js | 212 ++++++++--------- .../Cis/Abgabetool/AbgabeStudentDetail.js | 52 ++++- .../Cis/Abgabetool/AbgabetoolMitarbeiter.js | 140 ++++++------ .../Cis/Abgabetool/AbgabetoolStudent.js | 107 ++++++--- .../Cis/Abgabetool/DeadlineOverview.js | 2 +- public/js/plugins/Api.js | 1 - .../61164_abgabetool_quality_gates.php | 8 +- system/phrasesupdate.php | 216 +++++++++++++++++- 13 files changed, 634 insertions(+), 308 deletions(-) create mode 100644 application/config/abgabe.php diff --git a/application/config/abgabe.php b/application/config/abgabe.php new file mode 100644 index 000000000..e2092a367 --- /dev/null +++ b/application/config/abgabe.php @@ -0,0 +1,9 @@ + self::PERM_LOGGED, 'getStudentProjektarbeiten' => self::PERM_LOGGED, // TODO: abgabetool berechtigung? 'getStudentProjektabgaben' => self::PERM_LOGGED, 'postStudentProjektarbeitZwischenabgabe' => self::PERM_LOGGED, @@ -70,6 +71,22 @@ class Abgabe extends FHCAPI_Controller //------------------------------------------------------------------------------------------------------------------ // Public methods + /** + * loads config related to abgabetool, found in application/config/abgabe + */ + public function getConfig() { + $this->load->config('abgabe'); + $old_abgabe_beurteilung_link =$this->config->item('old_abgabe_beurteilung_link'); + $turnitin_link =$this->config->item('turnitin_link'); + + $ret = array( + 'old_abgabe_beurteilung_link' => $old_abgabe_beurteilung_link, + 'turnitin_link' => $turnitin_link + ); + + $this->terminateWithSuccess($ret); + } + /** * fetches all projektabgabetermine for a given projektarbeit_id used in cis4 student abgabetool */ @@ -116,9 +133,19 @@ class Abgabe extends FHCAPI_Controller $isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID()); if ($isMitarbeiter && $isZugeteilterBetreuer){ - $projektarbeiten = $this->ProjektarbeitModel->getStudentProjektarbeitenWithBetreuer($uid); + $result = $this->ProjektarbeitModel->getStudentProjektarbeitenWithBetreuer($uid); } else { - $projektarbeiten = $this->ProjektarbeitModel->getStudentProjektarbeitenWithBetreuer(getAuthUID()); + $result = $this->ProjektarbeitModel->getStudentProjektarbeitenWithBetreuer(getAuthUID()); + } + + $projektarbeiten = getData($result); + + // TODO: save access to this, array could be empty + foreach($projektarbeiten as $pa) { + $result = $this->ProjektarbeitModel->getProjektbetreuerEmail($pa->projektarbeit_id); + + // TODO: save access + $pa->email = getData($result)[0]->private_email; } $this->terminateWithSuccess(array($projektarbeiten, DOMAIN, $uid)); @@ -327,12 +354,8 @@ class Abgabe extends FHCAPI_Controller $maildata['parbeituebersichtlink'] = "

Zur Projektarbeitsübersicht

"; $maildata['bewertunglink'] = $num_rows_sem >= 1 && $paabgabetyp_kurzbz == 'end' ? "

Zur Beurteilung der Arbeit

" : ""; $maildata['token'] = ""; - - // TODO: clarify if all betreuer are mitarbeiter and have benutzer entries - // or if uid = null has to be checked WITH - // 'CASE WHEN tbl_benutzer.uid IS NULL THEN kontakt ELSE tbl_benutzer.uid || '@".DOMAIN."' END AS email' - $email = $this->getBetreuerEmail($bperson_id); + $email = $this->getProjektbetreuerEmail($projektarbeit_id); if(!$email) $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailBegutachter'), 'general'); @@ -401,12 +424,7 @@ class Abgabe extends FHCAPI_Controller $zweitbetmaildata['parbeituebersichtlink'] = $intern ? $maildata['parbeituebersichtlink'] : ""; $zweitbetmaildata['bewertunglink'] = $num_rows_sem >= 1 ? "

Zur Beurteilung der Arbeit

" : ""; $zweitbetmaildata['token'] = $num_rows_sem >= 1 && isset($begutachterMitToken->zugangstoken) && !$intern ? "

Zugangstoken: " . $begutachterMitToken->zugangstoken . "

" : ""; - - - $email = $this->getBetreuerEmail($bperson_id); - - if(!$email) $this->terminateWithError($this->p->t('abgabetool', 'fehlerMailBegutachter'), 'general'); - + $mailres = sendSanchoMail( 'ParbeitsbeurteilungEndupload', @@ -464,12 +482,13 @@ class Abgabe extends FHCAPI_Controller $fixtermin = $_POST['fixtermin']; $kurzbz = $_POST['kurzbz']; $note = $_POST['note']; - $upload_required = $_POST['upload_required']; + $upload_allowed = $_POST['upload_allowed']; + $betreuer_person_id = $_POST['betreuer_person_id']; if (!isset($projektarbeit_id) || isEmptyString($projektarbeit_id) || !isset($paabgabe_id) || isEmptyString($paabgabe_id) || !isset($datum) || isEmptyString($datum) - || !isset($datum) || isEmptyString($datum) + || !isset($kurzbz) || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); @@ -484,7 +503,7 @@ class Abgabe extends FHCAPI_Controller 'datum' => $datum, 'kurzbz' => $kurzbz, 'note' => $note, - 'upload_required' => $upload_required, + 'upload_allowed' => $upload_allowed, 'insertvon' => getAuthUID(), 'insertamum' => date('Y-m-d H:i:s') ) @@ -499,24 +518,37 @@ class Abgabe extends FHCAPI_Controller 'datum' => $datum, 'kurzbz' => $kurzbz, 'note' => $note, - 'upload_required' => $upload_required, + 'upload_allowed' => $upload_allowed, 'updatevon' => getAuthUID(), 'updateamum' => date('Y-m-d H:i:s') ) ); } - - $paabgabe_id = $this->getDataOrTerminateWithError($result); - - $paabgabe = $this->PaabgabeModel->load($paabgabe_id); // check if $paaabgabe is a qual gate and its note is deemed negative // -> send email to student with that info + $paabgabe_id = $this->getDataOrTerminateWithError($result); - // TODO: DEFAULT NOTE 9 OR DEFAULT NOTE NULL? 9 COUNTS AS NEGATIV :/ + $result = $this->PaabgabeModel->load($paabgabe_id); + $paabgabeArr = $this->getDataOrTerminateWithError($result); + $paabgabe = $paabgabeArr[0]; + $this->addMeta('paabgabe', $paabgabeArr); + + // check if abgabe even has note + if($paabgabe->note) { + $this->load->model('education/Note_model', 'NoteModel'); + $result = $this->NoteModel->load($paabgabe->note); + $noteArr = $this->getDataOrTerminateWithError($result); + $note = $noteArr[0]; + if($note->positiv === false) { + $this->addMeta('noteNegativ', true); + + $this->sendQualGateNegativEmail($projektarbeit_id, $betreuer_person_id, $paabgabe); + } + } - $this->terminateWithSuccess($result); + $this->terminateWithSuccess($paabgabe); } public function deleteProjektarbeitAbgabe() { @@ -556,7 +588,7 @@ class Abgabe extends FHCAPI_Controller if (!isset($projektarbeit_ids) || !is_array($projektarbeit_ids) || empty($projektarbeit_ids) || !isset($datum) || isEmptyString($datum) - || !isset($kurzbz) || isEmptyString($kurzbz) + || !isset($kurzbz) || !isset($bezeichnung) || isEmptyString($bezeichnung) || !isset($paabgabetyp_kurzbz) || isEmptyString($paabgabetyp_kurzbz)) $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); @@ -664,11 +696,11 @@ class Abgabe extends FHCAPI_Controller $this->terminateWithSuccess($paabgabetypen); } - private function getBetreuerEmail($person_id) { - $this->load->model('education/Projektbetreuer_model', 'ProjektbetreuerModel'); - $result = $this->ProjektbetreuerModel->getBetreuerEmail($person_id); + private function getProjektbetreuerEmail($projektarbeit_id) { + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $result = $this->ProjektarbeitModel->getProjektbetreuerEmail($projektarbeit_id); $email = $this->getDataOrTerminateWithError($result); - return $email[0]->email; + return $email[0]->private_email; } //TODO: SWITCH TO NOTEN API ONCE NOTENTOOL IS IN MASTER TO AVOID DUPLICATE API @@ -685,7 +717,24 @@ class Abgabe extends FHCAPI_Controller $this->terminateWithSuccess($noten); } - private function sendQualGateNegativEmail($student_uid) { + private function sendQualGateNegativEmail($projektarbeit_id, $betreuer_person_id, $paabgabe) { + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $result = $this->ProjektarbeitModel->load($projektarbeit_id); + $projektarbeitArr = $this->getDataOrTerminateWithError($result); + $projektarbeit = $projektarbeitArr[0]; + + $result = $this->ProjektarbeitModel->getProjektbetreuerAnrede($betreuer_person_id); + $anredeArr = $this->getDataOrTerminateWithError($result); + $anrede = $anredeArr[0]; + + $student_uid = $projektarbeit->student_uid; + + $this->load->model('education/Paabgabetyp_model', 'PaabgabetypModel'); + $result = $this->PaabgabetypModel->load($paabgabe->paabgabetyp_kurzbz); + $paabgabetyp_kurzbzArr = $this->getDataOrTerminateWithError($result); + $paabgabetyp_kurzbz = $paabgabetyp_kurzbzArr[0]; + // Mail an Student wenn Qualgate negativ beurteilt wurde $student = new student(); if(!$student->load($student_uid)) @@ -696,21 +745,21 @@ class Abgabe extends FHCAPI_Controller $tomail = $student_uid.'@'.DOMAIN; - // TODO: emaildata + // TODO: datum format $data = array( - 'betreuerfullname' => $student->vorname, - 'qualgatebezeichnung' => $student->nachname, - 'datum' => $datum, - 'projektarbeitname' => $name + 'betreuerfullname' => $anrede->first, + 'qualgatebezeichnung' => $paabgabetyp_kurzbz->bezeichnung, + 'datum' => $paabgabe->datum, + 'projektarbeitname' => $projektarbeit->titel ); + $this->addMeta('$emaildata', $data); + $mailres = sendSanchoMail( 'QualGateNegativ', $data, $tomail, $subject ); - - return $mailres; } } \ No newline at end of file diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index b1971cea7..c87e9c187 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -168,7 +168,7 @@ class Projektarbeit_model extends DB_Model campus.tbl_paabgabe.kurzbz, campus.tbl_paabgabe.datum, campus.tbl_paabgabe.note, - campus.tbl_paabgabe.upload_required, + campus.tbl_paabgabe.upload_allowed, campus.tbl_paabgabetyp.paabgabetyp_kurzbz, campus.tbl_paabgabetyp.bezeichnung, campus.tbl_paabgabe.abgabedatum, @@ -189,7 +189,28 @@ class Projektarbeit_model extends DB_Model WHERE public.tbl_person.person_id= ?"; return $this->execReadOnlyQuery($qry_betr, [$bperson_id]); + } + + public function getProjektbetreuerEmail($projektarbeit_id) { + $qry = "SELECT ( + SELECT kontakt + FROM public.tbl_kontakt + WHERE kontakttyp = 'email' + AND person_id = pers.person_id + ORDER BY + CASE WHEN zustellung THEN 0 ELSE 1 END, + insertamum DESC NULLS LAST + LIMIT 1 + ) AS private_email + FROM lehre.tbl_projektarbeit pa + JOIN lehre.tbl_projektbetreuer USING (projektarbeit_id) + JOIN public.tbl_person pers USING (person_id) + LEFT JOIN public.tbl_benutzer ben USING (person_id) + LEFT JOIN public.tbl_mitarbeiter ma ON ben.uid = ma.mitarbeiter_uid + WHERE (ben.aktiv OR ben.aktiv IS NULL) + AND projektarbeit_id = ?"; + return $this->execReadOnlyQuery($qry, [$projektarbeit_id]); } public function getProjektarbeitBenutzer($uid) { @@ -225,7 +246,7 @@ class Projektarbeit_model extends DB_Model FROM (SELECT tbl_person.vorname, tbl_person.nachname, tbl_studiengang.typ, tbl_studiengang.kurzbz, tbl_projektarbeit.projekttyp_kurzbz, tbl_projekttyp.bezeichnung, tbl_projektarbeit.titel, tbl_projektarbeit.projektarbeit_id, - tbl_projektbetreuer.betreuerart_kurzbz, tbl_betreuerart.beschreibung AS betreuerart_beschreibung, + tbl_projektbetreuer.person_id as betreuer_person_id, tbl_projektbetreuer.betreuerart_kurzbz, tbl_betreuerart.beschreibung AS betreuerart_beschreibung, tbl_benutzer.uid, tbl_student.matrikelnr, tbl_lehreinheit.studiensemester_kurzbz FROM lehre.tbl_projektarbeit LEFT JOIN lehre.tbl_projektbetreuer using(projektarbeit_id) diff --git a/application/models/education/Projektbetreuer_model.php b/application/models/education/Projektbetreuer_model.php index ae78b96d9..95950bf95 100644 --- a/application/models/education/Projektbetreuer_model.php +++ b/application/models/education/Projektbetreuer_model.php @@ -231,40 +231,4 @@ class Projektbetreuer_model extends DB_Model return $this->execQuery($qry, array($projektarbeit_id, $betreuer_person_id)); } - - /** - * Gets email of a Betreuer for a Projektarbeit. - * Projektarbeitbetreuer can be external employees, which should be contacted on their private - * email contact, if they have one. Internal Betreuer should be contacted on their "uid@DOMAIN" adress. - * @param int betreuer_person_id - * @return object success or error - */ - public function getBetreuerEmail($betreuer_person_id) { - // TODO: check if benutzer uid exists, not fixangestellt - - $qry =" - SELECT uid, - CASE - WHEN public.tbl_mitarbeiter.fixangestellt = false - THEN ( - SELECT kontakt AS email - FROM public.tbl_kontakt - WHERE - public.tbl_kontakt.person_id = ? AND - kontakttyp = 'email' - ) - - ELSE ( - SELECT public.tbl_benutzer.uid || '@' || '".DOMAIN."' AS email - FROM public.tbl_benutzer - WHERE person_id = ? - ) - END AS email - FROM public.tbl_benutzer - JOIN public.tbl_mitarbeiter ON (public.tbl_benutzer.uid = public.tbl_mitarbeiter.mitarbeiter_uid) - WHERE person_id = ? - "; - - return $this->execReadOnlyQuery($qry, array($betreuer_person_id, $betreuer_person_id, $betreuer_person_id)); - } } diff --git a/public/js/api/factory/abgabe.js b/public/js/api/factory/abgabe.js index 0602a218c..67e67f385 100644 --- a/public/js/api/factory/abgabe.js +++ b/public/js/api/factory/abgabe.js @@ -1,4 +1,10 @@ export default { + getConfig() { + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getConfig' + }; + }, getStudentProjektarbeiten(uid) { return { method: 'get', @@ -51,12 +57,13 @@ export default { paabgabe_id: termin.paabgabe_id, paabgabetyp_kurzbz: termin.bezeichnung.paabgabetyp_kurzbz, datum: termin.datum, - note: termin.note, - upload_required: termin.upload_required, + note: termin.note_pk, + upload_allowed: termin.upload_allowed, fixtermin: termin.fixtermin, insertvon: termin.insertvon, kurzbz: termin.kurzbz, - projektarbeit_id: termin.projektarbeit_id + projektarbeit_id: termin.projektarbeit_id, + betreuer_person_id: termin.betreuer_person_id } }; }, diff --git a/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js index c70c40ba7..ca8d92cd8 100644 --- a/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js +++ b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js @@ -13,7 +13,7 @@ export const AbgabeMitarbeiterDetail = { Textarea: primevue.textarea, VueDatePicker }, - inject: ['abgabeTypeOptions', 'allowedNotenOptions'], + inject: ['abgabeTypeOptions', 'allowedNotenOptions', 'turnitin_link', 'old_abgabe_beurteilung_link'], props: { projektarbeit: { type: Object, @@ -22,7 +22,6 @@ 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 @@ -34,18 +33,15 @@ export const AbgabeMitarbeiterDetail = { }, saveTermin(termin) { const paabgabe_id = termin.paabgabe_id - // 9 => magic number for "noch nicht eingetragen" - termin.note = termin.note?.note ?? 9 + termin.note_pk = termin.note?.note ?? null + termin.betreuer_person_id = this.projektarbeit.betreuer_person_id this.$api.call(ApiAbgabe.postProjektarbeitAbgabe(termin)).then( (res) => { if(res?.meta?.status == 'success') { this.$fhcAlert.alertSuccess(this.$p.t('ui/gespeichert')) - if(paabgabe_id === -1) { // new abgabe has been inserted - termin.paabgabe_id = res?.data?.retval - + termin.paabgabe_id = res?.data?.paabgabe_id this.projektarbeit.abgabetermine.push({ // new abgatermin row - 'paabgabe_id': -1, 'projektarbeit_id': this.projektarbeit.projektarbeit_id, 'fixtermin': false, @@ -53,7 +49,7 @@ export const AbgabeMitarbeiterDetail = { 'datum': new Date().toISOString().split('T')[0], 'paabgabetyp_kurzbz': termin.paabgabetyp_kurzbz, 'note': this.allowedNotenOptions.find(opt => opt.note == termin.note?.note), - 'upload_required': termin.upload_required, + 'upload_allowed': termin.upload_allowed, 'bezeichnung': this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz === termin.paabgabetyp_kurzbz), 'abgabedatum': null, 'insertvon': this.viewData?.uid ?? '', @@ -61,12 +57,9 @@ export const AbgabeMitarbeiterDetail = { 'allowedToDelete': true }) } - - } else if(res?.meta?.status == 'error'){ this.$fhcAlert.alertError() } - }) }, deleteTermin(termin) { @@ -76,8 +69,6 @@ export const AbgabeMitarbeiterDetail = { // this.$p.t('global/tooltipLektorDeleteKontrolle', [this.$entryParams.permissions.kontrolleDeleteMaxReach ]) const deletedTerminIndex = this.projektarbeit.abgabetermine.findIndex(t => t.paabgabe_id === termin.paabgabe_id) this.projektarbeit.abgabetermine.splice(deletedTerminIndex, 1) - - } else if(res?.meta?.status == 'error'){ this.$fhcAlert.alertError() } @@ -92,15 +83,13 @@ export const AbgabeMitarbeiterDetail = { return true; }, downloadAbgabe(termin) { - // TODO: test this.$api.call(ApiAbgabe.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid)) - // this.$fhcApi.factory.lehre.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid) }, dateDiffInDays(datum, today){ const oneDayMs = 1000 * 60 * 60 * 24 return Math.round((new Date(datum) - new Date(today)) / oneDayMs) }, - getDateStyle(termin) { + getDateStyle(termin, mode) { const datum = new Date(termin.datum) const abgabedatum = new Date(termin.abgabedatum) @@ -108,21 +97,31 @@ export const AbgabeMitarbeiterDetail = { // https://wiki.fhcomplete.info/doku.php?id=cis:abgabetool_fuer_studierende let color = 'white' let fontColor = 'black' + let icon = ''; if (termin.abgabedatum === null) { if(datum < today) { color = 'red' fontColor = 'white' + icon = 'fa-triangle-exclamation' } else if (datum > today && this.dateDiffInDays(datum, today) <= 12) { color = 'yellow' + icon = 'fa-circle-exclamation' } } else if(abgabedatum > datum) { color = 'pink' // aka "hellrot" fontColor = 'white' + icon = 'fa-circle-question' } else { color = 'green' + icon = 'fa-square-check' } - return `font-color: ${fontColor} ; background-color: ${color}; border-radius: 50%;` + //return `font-color: ${fontColor} ; background-color: ${color}; border-radius: 50%;` + if( typeof mode !== 'undefined' || mode === 'icon') { + return icon; + } else { + return 'abgabe-zieldatum-border-' + color; + } }, openBeurteilungLink(link) { window.open(link, '_blank') @@ -153,8 +152,7 @@ export const AbgabeMitarbeiterDetail = { window.open(link, '_blank') }, openPlagiatcheck() { - // todo: hardcoded turnitin link? - const link = "https://technikum-wien.turnitin.com/sso/sp/redwood/saml/5IyfmBr2OcSIaWQTKlFCGj/start" + const link = this.turnitin_link window.open(link, '_blank') }, openBenotung() { @@ -175,8 +173,17 @@ export const AbgabeMitarbeiterDetail = { }, endUploadVorhanden(){ return this.projektarbeit?.abgabetermine.find(abgabe => abgabe.paabgabetyp_kurzbz === 'end' && abgabe.abgabedatum !== null) + }, + qualityGateTerminAvailable() { + let qgatefound = false + this.projektarbeit?.abgabetermine.forEach(abgabe => { + if(abgabe.bezeichnung?.paabgabetyp_kurzbz == 'qualgate1' + || abgabe?.bezeichnung?.paabgabetyp_kurzbz == 'qualgate2') { + qgatefound = true + } + }) + return qgatefound } - }, created() { @@ -185,7 +192,7 @@ export const AbgabeMitarbeiterDetail = { }, template: ` -
+
{{$p.t('abgabetool/c4abgabeMitarbeiterbereich')}}
@@ -199,20 +206,20 @@ export const AbgabeMitarbeiterDetail = {
- Kein Endupload vorhanden! + {{ $p.t('abgabetool/c4noEnduploadFound') }}
@@ -220,8 +227,8 @@ export const AbgabeMitarbeiterDetail = {
@@ -230,86 +237,87 @@ export const AbgabeMitarbeiterDetail = {
-
{{$p.t('abgabetool/c4fixtermin')}}
-
{{$p.t('abgabetool/c4zieldatum')}}
-
{{$p.t('abgabetool/c4abgabetyp')}}
-
{{$p.t('abgabetool/c4note')}}
-
{{$p.t('abgabetool/c4upload_required')}}
-
{{$p.t('abgabetool/c4abgabekurzbz')}}
-
{{$p.t('abgabetool/c4abgabedatum')}}
-
- +
{{$p.t('abgabetool/c4fixtermin')}}
+
+
{{$p.t('abgabetool/c4zieldatum')}}
+
{{$p.t('abgabetool/c4abgabetyp')}}
+
{{$p.t('abgabetool/c4note')}}
+
{{$p.t('abgabetool/c4upload_allowed')}}
+
{{$p.t('abgabetool/c4abgabekurzbz')}}
+
{{$p.t('abgabetool/c4abgabedatum')}}
+
+ +
keine Termine gefunden!
-

+ + +
-
-
- +
+
+ + + +
+
+
+ - -
-
-
- - -
-
- - -
-
- - -
-
- -
-
- {{ termin.abgabedatum?.split("-").reverse().join(".") }} - - - -
-
-
-
- -
-
- -
+ v-model="termin.bezeichnung" + :options="abgabeTypeOptions" + :optionLabel="getOptionLabelAbgabetyp"> + +
+
+ + +
+
+ + +
+
+ +
+
+ {{ termin.abgabedatum?.split("-").reverse().join(".") }} + + + +
+
+ +
diff --git a/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js b/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js index 3271ed97f..be44b0441 100644 --- a/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js +++ b/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js @@ -15,6 +15,7 @@ export const AbgabeStudentDetail = { Textarea: primevue.textarea, VueDatePicker }, + inject: ['notenOptions'], props: { projektarbeit: { type: Object, @@ -83,9 +84,7 @@ export const AbgabeStudentDetail = { this.$refs.modalContainerEnduploadZusatzdaten.hide() }, downloadAbgabe(termin) { - // TODO: test this.$api.call(ApiAbgabe.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid)) - // this.$fhcApi.factory.lehre.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid) }, formatDate(dateParam) { const date = new Date(dateParam) @@ -181,6 +180,10 @@ export const AbgabeStudentDetail = { }, getOptionLabel(option) { return option.sprache + }, + getTerminNoteBezeichnung(termin) { + const noteOpt = this.notenOptions.find(opt => opt.note == termin.note) + return noteOpt ? noteOpt.bezeichnung : '' } }, watch: { @@ -201,6 +204,16 @@ export const AbgabeStudentDetail = { }, getAllowedToSendEndupload() { return !this.eidAkzeptiert + }, + qualityGateTerminAvailable() { + let qgatefound = false + this.projektarbeit?.abgabetermine.forEach(abgabe => { + if(abgabe.paabgabetyp_kurzbz == 'qualgate1' + || abgabe.paabgabetyp_kurzbz == 'qualgate2') { + qgatefound = true + } + }) + return qgatefound } }, created() { @@ -221,8 +234,10 @@ export const AbgabeStudentDetail = {
{{$p.t('abgabetool/c4fixtermin')}}
{{$p.t('abgabetool/c4zieldatum')}}
-
{{$p.t('abgabetool/c4abgabetyp')}}
-
{{$p.t('abgabetool/c4abgabekurzbz')}}
+
{{$p.t('abgabetool/c4abgabetyp')}}
+
{{$p.t('abgabetool/c4note')}}
+
{{$p.t('abgabetool/c4upload_allowed')}}
+
{{$p.t('abgabetool/c4abgabekurzbz')}}
{{$p.t('abgabetool/c4abgabedatum')}}
{{$p.t('abgabetool/c4fileupload')}} @@ -250,14 +265,27 @@ export const AbgabeStudentDetail = {
-
{{ termin.bezeichnung }}
-
- +
{{ termin.bezeichnung }}
+
+ {{ getTerminNoteBezeichnung(termin) }}
-
+
+ + +
+
+ +
+
{{ termin.abgabedatum?.split("-").reverse().join(".") }} - +
@@ -267,8 +295,8 @@ export const AbgabeStudentDetail = {
@@ -289,7 +317,7 @@ export const AbgabeStudentDetail = {
-

Titel: {{ projektarbeit?.titel }}

+

{{$p.t('abgabetool/c4titel')}}: {{ projektarbeit?.titel }}

diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js b/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js index c16abc8a3..1e9d61056 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js @@ -19,7 +19,9 @@ export const AbgabetoolMitarbeiter = { provide() { return { abgabeTypeOptions: Vue.computed(() => this.abgabeTypeOptions), - allowedNotenOptions: Vue.computed(() => this.allowedNotenOptions) + allowedNotenOptions: Vue.computed(() => this.allowedNotenOptions), + turnitin_link: Vue.computed(() => this.turnitin_link), + old_abgabe_beurteilung_link: Vue.computed(() => this.old_abgabe_beurteilung_link) } }, props: { @@ -34,6 +36,8 @@ export const AbgabetoolMitarbeiter = { }, data() { return { + turnitin_link: null, + old_abgabe_beurteilung_link: null, saving: false, loading: false, abgabeTypeOptions: null, @@ -59,9 +63,9 @@ export const AbgabetoolMitarbeiter = { tableBuiltResolve: null, tableBuiltPromise: null, abgabeTableOptions: { - height: 700, + minHeight: 250, index: 'projektarbeit_id', - layout: 'fitDataStretch', + layout: 'fitColumns', placeholder: this.$p.t('global/noDataAvailable'), selectable: true, selectableCheck: this.selectionCheck, @@ -80,13 +84,13 @@ export const AbgabetoolMitarbeiter = { {title: Vue.computed(() => this.$p.t('abgabetool/c4details')), field: 'details', formatter: this.detailFormatter, widthGrow: 1, tooltip: false}, {title: Vue.computed(() => this.$p.t('abgabetool/c4personenkennzeichen')), field: 'pkz', formatter: this.pkzTextFormatter, widthGrow: 1, tooltip: false}, {title: Vue.computed(() => this.$p.t('abgabetool/c4kontakt')), field: 'mail', formatter: this.mailFormatter, widthGrow: 1, tooltip: false}, - {title: Vue.computed(() => this.$p.t('abgabetool/c4vorname')), field: 'vorname', formatter: this.centeredTextFormatter, widthGrow: 1}, + {title: Vue.computed(() => this.$p.t('abgabetool/c4vorname')), field: 'vorname', formatter: this.centeredTextFormatter,widthGrow: 1}, {title: Vue.computed(() => this.$p.t('abgabetool/c4nachname')), field: 'nachname', formatter: this.centeredTextFormatter, widthGrow: 1}, {title: Vue.computed(() => this.$p.t('abgabetool/c4projekttyp')), field: 'projekttyp_kurzbz', formatter: this.centeredTextFormatter, widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('abgabetool/c4stg')), field: 'stg', 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: '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/c4betreuerart')), field: 'betreuerart_beschreibung',formatter: this.centeredTextFormatter, widthGrow: 8} + {title: Vue.computed(() => this.$p.t('abgabetool/c4betreuerart')), field: 'betreuerart_beschreibung',formatter: this.centeredTextFormatter, widthGrow: 1} ], persistence: false, }, @@ -209,7 +213,7 @@ export const AbgabetoolMitarbeiter = { 'kurzbz': '', 'datum': new Date().toISOString().split('T')[0], 'note': this.allowedNotenOptions.find(opt => opt.note == 9), - 'upload_required': false, + 'upload_allowed': false, 'paabgabetyp_kurzbz': '', 'bezeichnung': '', 'abgabedatum': null, @@ -227,7 +231,6 @@ export const AbgabetoolMitarbeiter = { paabgabetyp_kurzbz: termin.paabgabetyp_kurzbz } }) - pa.betreuer = this.buildBetreuer(pa) pa.student_uid = details.student_uid pa.student = `${pa.vorname} ${pa.nachname}` @@ -280,10 +283,6 @@ export const AbgabetoolMitarbeiter = { buildStg(projekt) { return (projekt.typ + projekt.kurzbz)?.toUpperCase() }, - buildBetreuer(abgabe) { - // TODO: preload and insert own titled name of betreuer somehow - return abgabe.betreuerart_beschreibung + ': ' + (abgabe.btitelpre ? abgabe.btitelpre + ' ' : '') + abgabe.bvorname + ' ' + abgabe.bnachname + (abgabe.btitelpost ? ' ' + abgabe.btitelpost : '') - }, setupData(data){ this.projektarbeiten = data[0] this.domain = data[1] @@ -337,7 +336,7 @@ export const AbgabetoolMitarbeiter = { if(!tableDataSet) return const rect = tableDataSet.getBoundingClientRect(); - this.abgabeTableOptions.height = window.visualViewport.height - rect.top + this.abgabeTableOptions.height = window.visualViewport.height - rect.top - 80 this.$refs.abgabeTable.tabulator.setHeight(this.abgabeTableOptions.height) }, async setupMounted() { @@ -346,7 +345,6 @@ export const AbgabetoolMitarbeiter = { this.loadProjektarbeiten() - this.$refs.verticalsplit.collapseBottom() this.calcMaxTableHeight() @@ -359,6 +357,15 @@ export const AbgabetoolMitarbeiter = { }, created() { + // fetch config to avoid hard coded links + this.$api.call(ApiAbgabe.getConfig()).then(res => { + this.turnitin_link = res.data?.turnitin_link + this.old_abgabe_beurteilung_link = res.data?.old_abgabe_beurteilung_link + }).catch(e => { + console.log(e) + this.loading = false + }) + // fetch noten options //TODO: SWITCH TO NOTEN API ONCE NOTENTOOL IS IN MASTER TO AVOID DUPLICATE API this.$api.call(ApiAbgabe.getNoten()).then(res => { @@ -367,7 +374,6 @@ export const AbgabetoolMitarbeiter = { this.allowedNotenOptions = this.notenOptions.filter( opt => opt.bezeichnung === 'Bestanden' || opt.bezeichnung === 'Nicht bestanden' - || opt.bezeichnung === 'Noch nicht eingetragen' ) }).catch(e => { this.loading = false @@ -385,7 +391,7 @@ export const AbgabetoolMitarbeiter = { }, template: ` + dialogClass="modal-lg"> + +
- - - - - - - + + + + + + +
`, }; diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js b/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js index bfd5da01b..2a1827b4e 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js @@ -10,6 +10,11 @@ export const AbgabetoolStudent = { AbgabeDetail, VerticalSplit }, + provide() { + return { + notenOptions: Vue.computed(() => this.notenOptions) + } + }, props: { student_uid_prop: { default: null @@ -25,6 +30,7 @@ export const AbgabetoolStudent = { }, data() { return { + notenOptions: null, tabulatorUuid: Vue.ref(0), domain: '', student_uid: null, @@ -83,27 +89,42 @@ export const AbgabetoolStudent = { ]}; }, methods: { - checkQualityGates(termine, enduploadtermin) { - return true + checkQualityGates(termine) { + let qgate1Passed = false + let qgate2Passed = false + + termine.forEach(t => { + const noteOption = this.notenOptions.find(opt => opt.note == t.note) + if(noteOption && noteOption.positiv) { + if(t.paabgabetyp_kurzbz == 'qualgate1') { + qgate1Passed = true + } else if(t.paabgabetyp_kurzbz == 'qualgate2') { + qgate2Passed = true + } + } + }) + + return qgate1Passed && qgate2Passed }, isPastDate(date) { return new Date(date) < new Date(Date.now()) }, setDetailComponent(details){ this.loadAbgaben(details).then((res)=> { - const pa = this.projektarbeiten?.retval?.find(projekarbeit => projekarbeit.projektarbeit_id == details.projektarbeit_id) + const pa = this.projektarbeiten?.find(projekarbeit => projekarbeit.projektarbeit_id == details.projektarbeit_id) pa.abgabetermine = res.data[0].retval pa.abgabetermine.forEach(termin => { termin.file = [] - // termin.allowedToUpload = true - + termin.allowedToUpload = false + // termin.datum = '2025-10-16' // TODO: fixtermin logic? - if(termin.bezeichnung == 'Endupload' && - (this.isPastDate(termin.datum) || this.checkQualityGates(pa.abgabetermine, termin))) { + if(termin.paabgabetyp_kurzbz == 'enda') { - // termin.allowedToUpload = false + termin.allowedToUpload = !this.isPastDate(termin.datum) && this.checkQualityGates(pa.abgabetermine) + } else if(termin.paabgabetyp_kurzbz == 'qualgate1' || termin.paabgabetyp_kurzbz == 'qualgate2') { + termin.allowedToUpload = termin.upload_allowed } else { - // termin.allowedToUpload = true + termin.allowedToUpload = true } }) @@ -111,7 +132,6 @@ export const AbgabetoolStudent = { pa.student_uid = this.student_uid this.selectedProjektarbeit = pa - this.$refs.verticalsplit.showBoth() @@ -150,8 +170,12 @@ export const AbgabetoolStudent = { tableResolve(resolve) { this.tableBuiltResolve = resolve }, - buildMailToLink(abgabe) { - return 'mailto:' + abgabe.mitarbeiter_uid +'@'+ this.domain + buildMailToLink(projekt) { + if(projekt.mitarbeiter_uid) { // standard + return 'mailto:' + projekt.mitarbeiter_uid +'@'+ this.domain + } else { // private + return 'mailto:' + projekt.email + } }, buildBetreuer(abgabe) { return abgabe.betreuerart_beschreibung + ': ' + (abgabe.btitelpre ? abgabe.btitelpre + ' ' : '') + abgabe.bvorname + ' ' + abgabe.bnachname + (abgabe.btitelpost ? ' ' + abgabe.btitelpost : '') @@ -160,7 +184,7 @@ export const AbgabetoolStudent = { this.projektarbeiten = data[0] this.domain = data[1] this.student_uid = data[2] - const d = data[0]?.retval?.map(projekt => { + const d = data[0]?.map(projekt => { let mode = 'detailTermine' if (projekt.babgeschickt || projekt.zweitbetreuer_abgeschickt) { @@ -213,7 +237,7 @@ export const AbgabetoolStudent = { if(!tableDataSet) return const rect = tableDataSet.getBoundingClientRect(); - this.abgabeTableOptions.height = window.visualViewport.height - rect.top + this.abgabeTableOptions.height = window.visualViewport.height - rect.top - 100 this.$refs.abgabeTable.tabulator.setHeight(this.abgabeTableOptions.height) }, async setupMounted() { @@ -223,7 +247,7 @@ export const AbgabetoolStudent = { this.loadProjektarbeiten() this.$refs.verticalsplit.collapseBottom() - //this.calcMaxTableHeight() + this.calcMaxTableHeight() } }, watch: { @@ -235,34 +259,43 @@ export const AbgabetoolStudent = { } }, created() { + //TODO: SWITCH TO NOTEN API ONCE NOTENTOOL IS IN MASTER TO AVOID DUPLICATE API + this.$api.call(ApiAbgabe.getNoten()).then(res => { + this.notenOptions = res.data + }).catch(e => { + this.loading = false + }) }, mounted() { this.setupMounted() }, template: ` - - - - + +
+ + + + +
`, }; diff --git a/public/js/components/Cis/Abgabetool/DeadlineOverview.js b/public/js/components/Cis/Abgabetool/DeadlineOverview.js index 6f8347169..cc202b4b4 100644 --- a/public/js/components/Cis/Abgabetool/DeadlineOverview.js +++ b/public/js/components/Cis/Abgabetool/DeadlineOverview.js @@ -110,7 +110,7 @@ export const DeadlineOverview = { if(!tableDataSet) return const rect = tableDataSet.getBoundingClientRect(); - this.deadlineTableOptions.height = window.visualViewport.height - rect.top + this.deadlineTableOptions.height = window.visualViewport.height - rect.top - 30 this.$refs.deadlineTable.tabulator.setHeight(this.deadlineTableOptions.height) }, async setupMounted() { diff --git a/public/js/plugins/Api.js b/public/js/plugins/Api.js index e3e604d6c..43c2b3064 100644 --- a/public/js/plugins/Api.js +++ b/public/js/plugins/Api.js @@ -164,7 +164,6 @@ export default { return fhcApiAxios.post(uri, data, config); }, call(factory, configoverwrite, form) { - debugger if (Array.isArray(factory)) { const $fhcAlert = app.config.globalProperties.$fhcAlert; const $api = app.config.globalProperties.$api; diff --git a/system/dbupdate_3.4/61164_abgabetool_quality_gates.php b/system/dbupdate_3.4/61164_abgabetool_quality_gates.php index b4f6fd7c9..1ec257bb1 100644 --- a/system/dbupdate_3.4/61164_abgabetool_quality_gates.php +++ b/system/dbupdate_3.4/61164_abgabetool_quality_gates.php @@ -34,7 +34,7 @@ if($result = $db->db_query("SELECT 1 FROM information_schema.columns WHERE table { $qry = "ALTER TABLE campus.tbl_paabgabe - ADD COLUMN note SMALLINT NOT NULL DEFAULT 9, + ADD COLUMN note SMALLINT DEFAULT NULL, ADD CONSTRAINT tbl_paabgabe_note_fkey FOREIGN KEY (note) REFERENCES lehre.tbl_note(note) @@ -47,16 +47,16 @@ if($result = $db->db_query("SELECT 1 FROM information_schema.columns WHERE table } } -if($result = $db->db_query("SELECT 1 FROM information_schema.columns WHERE table_schema = 'campus' AND table_name = 'tbl_paabgabe' AND column_name = 'upload_required'")) +if($result = $db->db_query("SELECT 1 FROM information_schema.columns WHERE table_schema = 'campus' AND table_name = 'tbl_paabgabe' AND column_name = 'upload_allowed'")) { if($db->db_num_rows($result) === 0) { $qry = "ALTER TABLE campus.tbl_paabgabe - ADD COLUMN IF NOT EXISTS upload_required boolean DEFAULT false;"; + ADD COLUMN IF NOT EXISTS upload_allowed boolean DEFAULT false;"; if(!$db->db_query($qry)) echo 'campus.tbl_paabgabe: '.$db->db_last_error().'
'; else - echo '
paabgabe column upload_required default false hinzugefuegt'; + echo '
paabgabe column upload_allowed default false hinzugefuegt'; } } \ No newline at end of file diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index dd23a1c4a..19cf6469f 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -41490,7 +41490,7 @@ array( ), array( 'sprache' => 'English', - 'text' => "details", + 'text' => "Details", 'description' => '', 'insertvon' => 'system' ) @@ -41510,7 +41510,7 @@ array( ), array( 'sprache' => 'English', - 'text' => "semester", + 'text' => "Semester", 'description' => '', 'insertvon' => 'system' ) @@ -41530,7 +41530,7 @@ array( ), array( 'sprache' => 'English', - 'text' => "degree program", + 'text' => "Degree program", 'description' => '', 'insertvon' => 'system' ) @@ -41550,7 +41550,7 @@ array( ), array( 'sprache' => 'English', - 'text' => "contact", + 'text' => "Contact", 'description' => '', 'insertvon' => 'system' ) @@ -41590,7 +41590,7 @@ array( ), array( 'sprache' => 'English', - 'text' => "project type", + 'text' => "Project type", 'description' => '', 'insertvon' => 'system' ) @@ -41610,7 +41610,7 @@ array( ), array( 'sprache' => 'English', - 'text' => "title", + 'text' => "Title", 'description' => '', 'insertvon' => 'system' ) @@ -41670,7 +41670,7 @@ array( ), array( 'sprache' => 'English', - 'text' => "target date", + 'text' => "Target date", 'description' => '', 'insertvon' => 'system' ) @@ -41730,7 +41730,7 @@ array( ), array( 'sprache' => 'English', - 'text' => "submission date", + 'text' => "Submission date", 'description' => '', 'insertvon' => 'system' ) @@ -41776,6 +41776,26 @@ array( ) ) ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4benoten', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Benoten", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Grade", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'abgabetool', @@ -41796,6 +41816,46 @@ array( ) ) ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4save', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Speichern", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Save", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4delete', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Löschen", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => "Delete", + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'abgabetool', @@ -42176,6 +42236,146 @@ array( ) ) ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4note', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Note", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Grade', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4upload_allowed', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Upload erlaubt", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Upload allowed', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4student_perspective', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Studentenansicht", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Student perspective', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4upload', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Hochladen", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Upload', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4plagiatcheck_link', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "zur Plagiatsprüfung", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Plagiarism check', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4plagiatcheck_link', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "zur Plagiatsprüfung", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Plagiarism check', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4noEnduploadFound', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => "Kein Endupload vorhanden!", + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'No final submission found!', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'abgabetool', From a560c335b8003e7bab771a74bc853c94a4029cce Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Tue, 2 Sep 2025 13:35:42 +0200 Subject: [PATCH 011/185] WIP responsive tabulator collapse abgabetool; paabgabe notiz column; --- .../views/CisRouterView/CisRouterView.php | 3 +- .../Cis/Abgabetool/AbgabetoolMitarbeiter.js | 41 +++-- .../Cis/Abgabetool/AbgabetoolStudent.js | 147 +++++++++++++----- .../61164_abgabetool_quality_gates.php | 14 ++ 4 files changed, 149 insertions(+), 56 deletions(-) diff --git a/application/views/CisRouterView/CisRouterView.php b/application/views/CisRouterView/CisRouterView.php index ab22fbb81..b56ed482e 100644 --- a/application/views/CisRouterView/CisRouterView.php +++ b/application/views/CisRouterView/CisRouterView.php @@ -33,7 +33,8 @@ $includesArray = array( 'vendor/moment/luxonjs/luxon.min.js' ), 'customJSModules' => array( - 'public/js/apps/Dashboard/Fhc.js' + 'public/js/apps/Dashboard/Fhc.js', + 'vendor/olifolkerd/tabulator5/src/js/modules/ResponsiveLayout/ResponsiveLayout.js' ), ); diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js b/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js index 1e9d61056..313029852 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolMitarbeiter.js @@ -236,8 +236,8 @@ export const AbgabetoolMitarbeiter = { this.selectedProjektarbeit = pa - - this.$refs.verticalsplit.showBoth() + this.$refs.modalContainerAbgabeDetail.show() + // this.$refs.verticalsplitthis.$refs.verticalsplit.showBoth() }) @@ -345,7 +345,7 @@ export const AbgabetoolMitarbeiter = { this.loadProjektarbeiten() - this.$refs.verticalsplit.collapseBottom() + // this.$refs.verticalsplit.collapseBottom() this.calcMaxTableHeight() } @@ -441,12 +441,27 @@ export const AbgabetoolMitarbeiter = { + + + + + + +
- - - - - + + + + + + +
`, diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js b/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js index 2a1827b4e..a63f781e9 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js @@ -2,10 +2,12 @@ import {CoreFilterCmpt} from "../../../components/filter/Filter.js"; import AbgabeDetail from "./AbgabeStudentDetail.js"; import VerticalSplit from "../../verticalsplit/verticalsplit.js"; import ApiAbgabe from '../../../api/factory/abgabe.js' +import BsModal from "../../Bootstrap/Modal.js"; export const AbgabetoolStudent = { name: "AbgabetoolStudent", components: { + BsModal, CoreFilterCmpt, AbgabeDetail, VerticalSplit @@ -43,16 +45,61 @@ export const AbgabetoolStudent = { minHeight: 250, index: 'projektarbeit_id', layout: 'fitColumns', + responsiveLayout: "collapse", placeholder: this.$p.t('global/noDataAvailable'), columns: [ - {title: Vue.computed(() => this.$p.t('abgabetool/c4details')), field: 'details', formatter: this.detailFormatter, widthGrow: 1, tooltip: false}, - {title: Vue.computed(() => this.$p.t('abgabetool/c4beurteilung')), field: 'beurteilung', formatter: this.beurteilungFormatter, widthGrow: 1, tooltip: false}, - {title: Vue.computed(() => this.$p.t('abgabetool/c4sem')), field: 'sem', formatter: this.centeredTextFormatter, widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('abgabetool/c4stg')), field: 'stg', formatter: this.centeredTextFormatter, widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('abgabetool/c4kontakt')), field: 'mail', formatter: this.mailFormatter, widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('abgabetool/c4betreuer')), field: 'betreuer', formatter: this.centeredTextFormatter,widthGrow: 2}, - {title: Vue.computed(() => this.$p.t('abgabetool/c4projekttyp')), field: 'typ', formatter: this.centeredTextFormatter, widthGrow: 1}, - {title: Vue.computed(() => this.$p.t('abgabetool/c4titel')), field: 'titel', formatter: this.centeredTextFormatter, widthGrow: 8} + { + formatter:"responsiveCollapse", + width:30, minWidth:30, hozAlign:"center", resizable:false, headerSort:false + }, + { + title: Vue.computed(() => this.$p.t('abgabetool/c4details')), field: 'details', + formatter: this.detailFormatter, + widthGrow: 1, tooltip: false + , responsive: 0, minWidth: 80 + }, + { + title: Vue.computed(() => this.$p.t('abgabetool/c4beurteilung')), field: 'beurteilung', + formatter: this.beurteilungFormatter, + widthGrow: 1, tooltip: false + , responsive: 0, minWidth: 80 + }, + { + title: Vue.computed(() => this.$p.t('abgabetool/c4sem')), field: 'sem', + formatter: this.centeredTextFormatter, + widthGrow: 1 + , responsive: 5, minWidth: 120 + }, + { + title: Vue.computed(() => this.$p.t('abgabetool/c4stg')), field: 'stg', + formatter: this.centeredTextFormatter, + widthGrow: 1 + , responsive: 6, minWidth: 120 + }, + { + title: Vue.computed(() => this.$p.t('abgabetool/c4kontakt')), field: 'mail', + formatter: this.mailFormatter, + widthGrow: 1 + , responsive: 0, minWidth: 80 + }, + { + title: Vue.computed(() => this.$p.t('abgabetool/c4betreuer')), field: 'betreuer', + formatter: this.centeredTextFormatter, + widthGrow: 2 + , responsive: 7, minWidth: 300 + }, + { + title: Vue.computed(() => this.$p.t('abgabetool/c4projekttyp')), field: 'typ', + formatter: this.centeredTextFormatter, + widthGrow: 1 + , responsive: 8, minWidth: 200 + }, + { + title: Vue.computed(() => this.$p.t('abgabetool/c4titel')), field: 'titel', + formatter: this.centeredTextFormatter, + widthGrow: 8 + , responsive: 1, minWidth: 420 + } ], persistence: false, }, @@ -132,8 +179,9 @@ export const AbgabetoolStudent = { pa.student_uid = this.student_uid this.selectedProjektarbeit = pa - - this.$refs.verticalsplit.showBoth() + + this.$refs.modalContainerAbgabeDetail.show() + // this.$refs.verticalsplit.showBoth() }) @@ -141,29 +189,29 @@ export const AbgabetoolStudent = { centeredTextFormatter(cell) { const val = cell.getValue() - return '
' + + return '
' + '

'+val+'

' }, detailFormatter(cell) { const val = cell.getValue() if(val.mode === 'detailTermine') { - return '
' + + return '
' + '
' } else if (val.mode === 'beurteilungDownload') { - return '
' + + return '
' + '
' } }, mailFormatter(cell) { const val = cell.getValue() - return '
' + + return '
' + '
' }, beurteilungFormatter(cell) { const val = cell.getValue() if(val) { - return '
' + + return '
' + '
' } else return '-' }, @@ -213,6 +261,11 @@ export const AbgabetoolStudent = { this.$refs.abgabeTable.tabulator.setColumns(this.abgabeTableOptions.columns) this.$refs.abgabeTable.tabulator.setData(d); + + Vue.nextTick(()=>{ + this.$refs.abgabeTable?.tabulator.setColumns(this.$refs.abgabeTable?.tabulator.getColumnDefinitions()) + + }) }, loadProjektarbeiten() { this.$api.call(ApiAbgabe.getStudentProjektarbeiten(this.student_uid_prop || this.viewData?.uid || null)) @@ -245,9 +298,15 @@ export const AbgabetoolStudent = { await this.tableBuiltPromise this.loadProjektarbeiten() + - this.$refs.verticalsplit.collapseBottom() - this.calcMaxTableHeight() + // window.addEventListener("resize", this.redrawHandler); + // this.$refs.verticalsplit.collapseBottom() + }, + redrawHandler() { + console.log('redrawHandler') + this.$refs.abgabeTable?.tabulator.setColumns(this.$refs.abgabeTable?.tabulator.getColumnDefinitions()) + this.$refs.abgabeTable?.tabulator.redraw(true) } }, watch: { @@ -270,32 +329,36 @@ export const AbgabetoolStudent = { mounted() { this.setupMounted() }, + unmounted() { + // window.removeEventListener("resize", this.redrawHandler); + }, template: ` - -
- - - - -
+ + + + + + +

{{$p.t('abgabetool/abgabetoolTitle')}}

+
+ + `, }; diff --git a/system/dbupdate_3.4/61164_abgabetool_quality_gates.php b/system/dbupdate_3.4/61164_abgabetool_quality_gates.php index 1ec257bb1..1584aae01 100644 --- a/system/dbupdate_3.4/61164_abgabetool_quality_gates.php +++ b/system/dbupdate_3.4/61164_abgabetool_quality_gates.php @@ -59,4 +59,18 @@ if($result = $db->db_query("SELECT 1 FROM information_schema.columns WHERE table else echo '
paabgabe column upload_allowed default false hinzugefuegt'; } +} + +if($result = $db->db_query("SELECT 1 FROM information_schema.columns WHERE table_schema = 'campus' AND table_name = 'tbl_paabgabe' AND column_name = 'notiz'")) +{ + if($db->db_num_rows($result) === 0) + { + $qry = "ALTER TABLE campus.tbl_paabgabe + ADD COLUMN IF NOT EXISTS notiz text DEFAULT NULL;"; + + if(!$db->db_query($qry)) + echo 'campus.tbl_paabgabe: '.$db->db_last_error().'
'; + else + echo "
paabgabe column notiz default '' hinzugefuegt"; + } } \ No newline at end of file From fd2ff27e22d16aab895e781bf9a5d21c3ac91d51 Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 3 Sep 2025 15:24:07 +0200 Subject: [PATCH 012/185] Added column prestudent_id to getStudentsByLv method query in Lehrveranstaltung_model.php --- application/models/education/Lehrveranstaltung_model.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 3eb4d33a2..63d1ca15c 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -316,7 +316,8 @@ class Lehrveranstaltung_model extends DB_Model (SELECT status_kurzbz FROM public.tbl_prestudentstatus WHERE prestudent_id=tbl_student.prestudent_id ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1) as status, tbl_bisio.bisio_id, tbl_bisio.von, tbl_bisio.bis, tbl_student.studiengang_kz AS stg_kz_student, tbl_zeugnisnote.note, tbl_mitarbeiter.mitarbeiter_uid, tbl_person.matr_nr, tbl_benutzer.uid, - UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel, tbl_studiengang.orgform_kurzbz, vw_student_lehrveranstaltung.semester, vw_student_lehrveranstaltung.studiensemester_kurzbz, vw_student_lehrveranstaltung.bezeichnung + UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel, tbl_studiengang.orgform_kurzbz, vw_student_lehrveranstaltung.semester, vw_student_lehrveranstaltung.studiensemester_kurzbz, vw_student_lehrveranstaltung.bezeichnung, + tbl_student.prestudent_id FROM campus.vw_student_lehrveranstaltung From 10d58d1a42f64649ef0110ccb9528519bd05efa4 Mon Sep 17 00:00:00 2001 From: Cristina Date: Wed, 3 Sep 2025 15:24:07 +0200 Subject: [PATCH 013/185] Added column prestudent_id to getStudentsByLv method query in Lehrveranstaltung_model.php --- application/models/education/Lehrveranstaltung_model.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 3eb4d33a2..e02c1ad0b 100644 --- a/application/models/education/Lehrveranstaltung_model.php +++ b/application/models/education/Lehrveranstaltung_model.php @@ -316,8 +316,8 @@ class Lehrveranstaltung_model extends DB_Model (SELECT status_kurzbz FROM public.tbl_prestudentstatus WHERE prestudent_id=tbl_student.prestudent_id ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1) as status, tbl_bisio.bisio_id, tbl_bisio.von, tbl_bisio.bis, tbl_student.studiengang_kz AS stg_kz_student, tbl_zeugnisnote.note, tbl_mitarbeiter.mitarbeiter_uid, tbl_person.matr_nr, tbl_benutzer.uid, - UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel, tbl_studiengang.orgform_kurzbz, vw_student_lehrveranstaltung.semester, vw_student_lehrveranstaltung.studiensemester_kurzbz, vw_student_lehrveranstaltung.bezeichnung - + UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel, tbl_studiengang.orgform_kurzbz, vw_student_lehrveranstaltung.semester, vw_student_lehrveranstaltung.studiensemester_kurzbz, vw_student_lehrveranstaltung.bezeichnung, + tbl_student.prestudent_id FROM campus.vw_student_lehrveranstaltung JOIN public.tbl_benutzer USING(uid) From 5f1c7537fb191a27726fcffde44ef7400e5be492 Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Thu, 4 Sep 2025 11:04:12 +0200 Subject: [PATCH 014/185] WIP --- .../controllers/api/frontend/v1/Abgabe.php | 15 +- public/js/apps/Dashboard/Fhc.js | 1 + .../Cis/Abgabetool/AbgabeStudentDetail.js | 248 +++++++++++++----- .../Cis/Abgabetool/AbgabetoolStudent.js | 42 ++- 4 files changed, 221 insertions(+), 85 deletions(-) diff --git a/application/controllers/api/frontend/v1/Abgabe.php b/application/controllers/api/frontend/v1/Abgabe.php index 345ead004..4ff260602 100644 --- a/application/controllers/api/frontend/v1/Abgabe.php +++ b/application/controllers/api/frontend/v1/Abgabe.php @@ -140,13 +140,16 @@ class Abgabe extends FHCAPI_Controller $projektarbeiten = getData($result); - // TODO: save access to this, array could be empty - foreach($projektarbeiten as $pa) { - $result = $this->ProjektarbeitModel->getProjektbetreuerEmail($pa->projektarbeit_id); - - // TODO: save access - $pa->email = getData($result)[0]->private_email; + if(count($projektarbeiten)) { + // TODO: save access to this, array could be empty + foreach($projektarbeiten as $pa) { + $result = $this->ProjektarbeitModel->getProjektbetreuerEmail($pa->projektarbeit_id); + + // TODO: save access + $pa->email = getData($result)[0]->private_email; + } } + $this->terminateWithSuccess(array($projektarbeiten, DOMAIN, $uid)); } diff --git a/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js index 473e1cf67..5295050a0 100644 --- a/public/js/apps/Dashboard/Fhc.js +++ b/public/js/apps/Dashboard/Fhc.js @@ -233,6 +233,7 @@ const app = Vue.createApp({ return { // provide injectable & watchable language property language: Vue.computed(() => this.$p.user_language), renderers: Vue.computed(() => this.renderers), + isMobile: this.isMobile } }, methods: { diff --git a/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js b/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js index be44b0441..e56ab90ca 100644 --- a/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js +++ b/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js @@ -13,9 +13,11 @@ export const AbgabeStudentDetail = { Checkbox: primevue.checkbox, Dropdown: primevue.dropdown, Textarea: primevue.textarea, + Accordion: primevue.accordion, + AccordionTab: primevue.accordiontab, VueDatePicker }, - inject: ['notenOptions'], + inject: ['notenOptions', 'isMobile'], props: { projektarbeit: { type: Object, @@ -184,6 +186,14 @@ export const AbgabeStudentDetail = { getTerminNoteBezeichnung(termin) { const noteOpt = this.notenOptions.find(opt => opt.note == termin.note) return noteOpt ? noteOpt.bezeichnung : '' + }, + getAccTabHeaderForTermin(termin) { + let tabTitle = '' + + const datumFormatted = this.formatDate(termin.datum) + tabTitle += termin.bezeichnung + ' ' + datumFormatted + + return tabTitle } }, watch: { @@ -230,79 +240,175 @@ export const AbgabeStudentDetail = {

{{projektarbeit?.betreuer}}

{{projektarbeit?.titel}}

-
-
-
{{$p.t('abgabetool/c4fixtermin')}}
-
{{$p.t('abgabetool/c4zieldatum')}}
-
{{$p.t('abgabetool/c4abgabetyp')}}
-
{{$p.t('abgabetool/c4note')}}
-
{{$p.t('abgabetool/c4upload_allowed')}}
-
{{$p.t('abgabetool/c4abgabekurzbz')}}
-
{{$p.t('abgabetool/c4abgabedatum')}}
-
- {{$p.t('abgabetool/c4fileupload')}} -
-
-
-
- - - -
-
-
- - - -
-
-
{{ termin.bezeichnung }}
-
- {{ getTerminNoteBezeichnung(termin) }} -
-
- - -
-
- -
-
- {{ termin.abgabedatum?.split("-").reverse().join(".") }} - - - -
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js b/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js index a63f781e9..e46f46579 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js @@ -12,6 +12,7 @@ export const AbgabetoolStudent = { AbgabeDetail, VerticalSplit }, + inject: ['isMobile'], provide() { return { notenOptions: Vue.computed(() => this.notenOptions) @@ -41,6 +42,8 @@ export const AbgabetoolStudent = { selectedProjektarbeit: null, tableBuiltResolve: null, tableBuiltPromise: null, + dataProcessedPromise: null, + dataProcessedResolve: null, abgabeTableOptions: { minHeight: 250, index: 'projektarbeit_id', @@ -103,12 +106,20 @@ export const AbgabetoolStudent = { ], persistence: false, }, - abgabeTableEventHandlers: [{ + abgabeTableEventHandlers: [ + { event: "tableBuilt", handler: async () => { this.tableBuiltResolve() } }, + { + event: "dataProcessed", + handler: async () => { + console.log('dataProcessed event') + this.dataProcessedResolve() + } + }, { event: "cellClick", handler: async (e, cell) => { @@ -218,6 +229,10 @@ export const AbgabetoolStudent = { tableResolve(resolve) { this.tableBuiltResolve = resolve }, + dataResolve(resolve) { + console.log('dataResolve') + this.dataProcessedResolve = resolve + }, buildMailToLink(projekt) { if(projekt.mitarbeiter_uid) { // standard return 'mailto:' + projekt.mitarbeiter_uid +'@'+ this.domain @@ -228,7 +243,7 @@ export const AbgabetoolStudent = { buildBetreuer(abgabe) { return abgabe.betreuerart_beschreibung + ': ' + (abgabe.btitelpre ? abgabe.btitelpre + ' ' : '') + abgabe.bvorname + ' ' + abgabe.bnachname + (abgabe.btitelpost ? ' ' + abgabe.btitelpost : '') }, - setupData(data){ + async setupData(data){ this.projektarbeiten = data[0] this.domain = data[1] this.student_uid = data[2] @@ -259,13 +274,23 @@ export const AbgabetoolStudent = { } }) - this.$refs.abgabeTable.tabulator.setColumns(this.abgabeTableOptions.columns) + // this.$refs.abgabeTable.tabulator.setColumns(this.abgabeTableOptions.columns) this.$refs.abgabeTable.tabulator.setData(d); + await this.dataProcessedPromise - Vue.nextTick(()=>{ - this.$refs.abgabeTable?.tabulator.setColumns(this.$refs.abgabeTable?.tabulator.getColumnDefinitions()) - }) + // TODO: proper event handling cleanup + + // todo in general fix this nasty race condition + const t = this.$refs.abgabeTable.tabulator; + t.on("renderComplete", () => { + // only if container width is small enough to trigger collapse + if (t.element.offsetWidth < 600 || this.isMobile) { + t.setColumns(t.getColumnDefinitions()); + t.redraw(true) + } + }); + }, loadProjektarbeiten() { this.$api.call(ApiAbgabe.getStudentProjektarbeiten(this.student_uid_prop || this.viewData?.uid || null)) @@ -295,8 +320,9 @@ export const AbgabetoolStudent = { }, async setupMounted() { this.tableBuiltPromise = new Promise(this.tableResolve) + this.dataProcessedPromise = new Promise(this.dataResolve) await this.tableBuiltPromise - + // this.$refs.abgabeTable.tabulator.setColumns(this.abgabeTableOptions.columns) this.loadProjektarbeiten() @@ -338,7 +364,7 @@ export const AbgabetoolStudent = { dialogClass="modal-fullscreen">