diff --git a/application/config/Events.php b/application/config/Events.php index 3e0a5248f..80a8f03b3 100644 --- a/application/config/Events.php +++ b/application/config/Events.php @@ -6,30 +6,30 @@ use CI3_Events as Events; Events::on('loadRenderers', function ($renderers) { $fhc_core_renderers =& $renderers(); $fhc_core_renderers["lehreinheit"] = array( - 'calendarEvent' => APP_ROOT.'public/js/components/Cis/Renderer/Lehreinheit/calendarEvent.js', - 'modalTitle' => APP_ROOT.'public/js/components/Cis/Renderer/Lehreinheit/modalTitle.js', - 'modalContent' => APP_ROOT.'public/js/components/Cis/Renderer/Lehreinheit/modalContent.js', - 'calendarEventStyles' => APP_ROOT.'public/css/Cis4/CoreCalendarEvents.css' + 'calendarEvent' => absoluteJsImportUrl('public/js/components/Cis/Renderer/Lehreinheit/calendarEvent.js'), + 'modalTitle' => absoluteJsImportUrl('public/js/components/Cis/Renderer/Lehreinheit/modalTitle.js'), + 'modalContent' => absoluteJsImportUrl('public/js/components/Cis/Renderer/Lehreinheit/modalContent.js'), + 'calendarEventStyles' => APP_ROOT . 'public/css/Cis4/CoreCalendarEvents.css' ); }); Events::on('loadRenderers', function ($renderers) { $fhc_core_renderers =& $renderers(); $fhc_core_renderers["reservierung"] = array( - 'calendarEvent' => APP_ROOT.'public/js/components/Cis/Renderer/Reservierungen/calendarEvent.js', - 'modalTitle' => APP_ROOT.'public/js/components/Cis/Renderer/Reservierungen/modalTitle.js', - 'modalContent' => APP_ROOT.'public/js/components/Cis/Renderer/Reservierungen/modalContent.js', - 'calendarEventStyles' => APP_ROOT.'public/css/Cis4/CoreCalendarEvents.css' + 'calendarEvent' => absoluteJsImportUrl('public/js/components/Cis/Renderer/Reservierungen/calendarEvent.js'), + 'modalTitle' => absoluteJsImportUrl('public/js/components/Cis/Renderer/Reservierungen/modalTitle.js'), + 'modalContent' => absoluteJsImportUrl('public/js/components/Cis/Renderer/Reservierungen/modalContent.js'), + 'calendarEventStyles' => APP_ROOT . 'public/css/Cis4/CoreCalendarEvents.css' ); }); Events::on('loadRenderers', function ($renderers) { $fhc_core_renderers =& $renderers(); $fhc_core_renderers["ferien"] = array( - 'calendarEvent' => APP_ROOT.'public/js/components/Cis/Renderer/Feiertage/calendarEvent.js', - 'modalTitle' => APP_ROOT.'public/js/components/Cis/Renderer/Feiertage/modalTitle.js', - 'modalContent' => APP_ROOT.'public/js/components/Cis/Renderer/Feiertage/modalContent.js', - 'calendarEventStyles' => APP_ROOT.'public/css/Cis4/CoreCalendarEvents.css' + 'calendarEvent' => absoluteJsImportUrl('public/js/components/Cis/Renderer/Feiertage/calendarEvent.js'), + 'modalTitle' => absoluteJsImportUrl('public/js/components/Cis/Renderer/Feiertage/modalTitle.js'), + 'modalContent' => absoluteJsImportUrl('public/js/components/Cis/Renderer/Feiertage/modalContent.js'), + 'calendarEventStyles' => APP_ROOT . 'public/css/Cis4/CoreCalendarEvents.css' ); }); diff --git a/application/config/abgabe.php b/application/config/abgabe.php new file mode 100644 index 000000000..f9b043a34 --- /dev/null +++ b/application/config/abgabe.php @@ -0,0 +1,38 @@ + cis4 +$config['URL_STUDENTS'] = 'cis.php/Cis/Abgabetool/Student'; +// used as APP_ROOT.URL_MITARBEITER -> old cis +$config['URL_MITARBEITER'] = 'index.ci.php/Cis/Abgabetool/Mitarbeiter'; +// used as APP_ROOT.URL_MITARBEITER -> old cis +$config['URL_ASSISTENZ'] = 'index.ci.php/Cis/Abgabetool/Assistenz'; + +// lehre.tbl_paabgabetyp bezeichnung +//$config['ALLOWED_ABGABETYPEN_BETREUER'] = ['Zwischenabgabe', 'Quality Gate 1', 'Quality Gate 2']; +$config['ALLOWED_ABGABETYPEN_BETREUER'] = ['abstract','zwischen', 'qualgate1', 'qualgate2']; // tbl_paabgabetyp pk +// paabgabetypen for which betreuer is benachrichtigt via sammelmail +$config['RELEVANT_PAABGABETYPEN_SAMMELMAIL_BETREUER'] = ['qualgate1', 'qualgate2', 'end']; +// paabgabetypen for which assistenz is benachrichtigt via sammelmail +$config['RELEVANT_PAABGABETYPEN_SAMMELMAIL_ASSISTENZ'] = ['end']; +// paabgabetypen for which student is benachrichtigt via sammelmail -> basically all of them but still defined for consistency +$config['RELEVANT_PAABGABETYPEN_SAMMELMAIL_STUDENT'] = ['qualgate1', 'qualgate2', 'zwischen', 'note', 'abstract', 'end', 'enda']; +//$config['ALLOWED_NOTEN_ABGABETOOL'] = ['Bestanden', 'Nicht bestanden']; +$config['ALLOWED_NOTEN_ABGABETOOL'] = [10, 14]; // tbl_note pk + +$config['beurteilung_link_fallback'] = 'addons/fhtw/content/projektbeurteilung/projektbeurteilungDocumentExport.php?projektarbeit_id=?&betreuerart_kurzbz=?&person_id=?'; + +$config['PROJEKTARBEITSBEURTEILUNG_MAIL_BASELINK_ERSTBEGUTACHTER'] = 'index.ci.php/extensions/FHC-Core-Projektarbeitsbeurteilung/ProjektarbeitsbeurteilungErstbegutachter'; +$config['PROJEKTARBEITSBEURTEILUNG_MAIL_BASELINK_ZWEITBEGUTACHTER'] = 'index.ci.php/extensions/FHC-Core-Projektarbeitsbeurteilung/ProjektarbeitsbeurteilungErstbegutachter'; + +$config['SIGNATUR_CHECK_PAABGABETYPEN'] = ['end']; + +// to be used as "https://moodle.technikum-wien.at/course/view.php?idnumber=dl{$stg_kz}" for stg specific moodle routing +$config['STG_MOODLE_LINK'] = 'https://moodle.technikum-wien.at/course/view.php?idnumber=dl'; diff --git a/application/config/cis.php b/application/config/cis.php index 8d3bc347e..430539392 100644 --- a/application/config/cis.php +++ b/application/config/cis.php @@ -4,7 +4,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); // CMS Content Id for CIS4 Menu Root -$config['cis_menu_root_content_id'] = 11087; +$config['cis_menu_root_content_id'] = 11091; // send Mails for ProfilUpdate $config['cis_send_profil_update_mails'] = true; // Vilesci CI BaseUrl diff --git a/application/config/javascript.php b/application/config/javascript.php index 6f82810e2..7b8342ef8 100644 --- a/application/config/javascript.php +++ b/application/config/javascript.php @@ -7,3 +7,6 @@ $config['use_vuejs_dev_version'] = false; $config['use_bundled_javascript'] = false; // systemerror_mailto use in FHC-Alert Plugin - if empty Link will not be rendered $config['systemerror_mailto'] = ''; +// use fhcomplete_build_version as path element after public (requires apache mod_rewrite) +// see /public/.htaccess_sample for details +$config['use_fhcomplete_build_version_in_path'] = false; diff --git a/application/config/routes.php b/application/config/routes.php index eba6688ff..aa4ba9db8 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -65,6 +65,13 @@ $route['Cis/LvPlan/.*'] = 'Cis/LvPlan/index/$1'; $route['Cis/MyLvPlan/.*'] = 'Cis/MyLvPlan/index/$1'; $route['Cis/MyLv/.*'] = 'Cis/MyLv/index/$1'; +$route['Abgabetool/Assistenz'] = 'Cis/Abgabetool/Assistenz'; +$route['Abgabetool/Assistenz/(:any)'] = 'Cis/Abgabetool/Assistenz/$1'; +$route['Abgabetool/Mitarbeiter'] = 'Cis/Abgabetool/Mitarbeiter'; +$route['Abgabetool/Student'] = 'Cis/Abgabetool/Student'; +$route['Abgabetool/Student/(:any)'] = 'Cis/Abgabetool/Student/$1'; +$route['Abgabetool/Deadlines'] = 'Cis/Abgabetool/Deadlines'; + // Studierendenverwaltung List Routes $route['api/frontend/v1/stv/[sS]tudents/inout'] = 'api/frontend/v1/stv/Students/index'; $route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})'] = 'api/frontend/v1/stv/Students/index'; diff --git a/application/controllers/Cis/Abgabetool.php b/application/controllers/Cis/Abgabetool.php index 1895f7472..04338b1a9 100644 --- a/application/controllers/Cis/Abgabetool.php +++ b/application/controllers/Cis/Abgabetool.php @@ -14,10 +14,10 @@ class Abgabetool extends Auth_Controller { parent::__construct([ 'index' => self::PERM_LOGGED, - 'getStudentProjektarbeitAbgabeFile' => self::PERM_LOGGED, - 'Mitarbeiter' => self::PERM_LOGGED, - 'Student' => self::PERM_LOGGED, - 'Deadlines' => self::PERM_LOGGED + 'Mitarbeiter' => array('basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw'), + 'Assistenz' => array('basis/abgabe_assistenz:rw'), + 'Student' => array('basis/abgabe_student:rw', 'basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw'), + 'Deadlines' => array('basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw') ]); } @@ -29,80 +29,69 @@ class Abgabetool extends Auth_Controller */ public function index() { + // TODO: routing from index based on berechtigung? $viewData = array( 'uid'=>getAuthUID(), ); - $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Abgabetool']); + if(defined('CIS4') && CIS4) { + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Abgabetool']); + } else { + $this->load->view('Cis/Abgabetool.php', ['uid' => getAuthUID(), 'route' => 'Abgabetool']); + } } - public function Student() + public function Student($student_uid_prop = '') { - $viewData = array( 'uid'=>getAuthUID(), ); - - $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'AbgabetoolStudent']); + + if(defined('CIS4') && CIS4) { + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'AbgabetoolStudent']); + } else { + $this->load->view('Cis/Abgabetool.php', ['uid' => getAuthUID(), 'route' => 'AbgabetoolStudent', 'student_uid_prop' => $student_uid_prop]); + } } public function Mitarbeiter() { - $viewData = array( 'uid'=>getAuthUID(), ); - $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'AbgabetoolMitarbeiter']); + if(defined('CIS4') && CIS4) { + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'AbgabetoolMitarbeiter']); + } else { + $this->load->view('Cis/Abgabetool.php', ['uid' => getAuthUID(), 'route' => 'AbgabetoolMitarbeiter']); + } } + public function Assistenz($stg_kz_prop = '') + { + + $viewData = array( + 'uid'=>getAuthUID(), + ); + + if(defined('CIS4') && CIS4) { + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'AbgabetoolAssistenz']); + } else { + $this->load->view('Cis/Abgabetool.php', ['uid' => getAuthUID(), 'route' => 'AbgabetoolAssistenz', 'stg_kz_prop' => $stg_kz_prop]); + } + } + public function Deadlines() { - $viewData = array( 'uid'=>getAuthUID(), ); - $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'DeadlinesOverview']); - } - - - public function getStudentProjektarbeitAbgabeFile() - { - $this->_ci =& get_instance(); - $this->_ci->load->helper('download'); - - $paabgabe_id = $this->_ci->input->get('paabgabe_id'); - $student_uid = $this->_ci->input->get('student_uid'); - - if (!isset($paabgabe_id) || isEmptyString($paabgabe_id) || !isset($student_uid) || isEmptyString($student_uid)) - $this->terminateWithJsonError($this->p->t('global', 'wrongParameters'), 'general'); - - $this->_ci->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); - - $isZugeteilterBetreuer = count($this->_ci->ProjektarbeitModel->checkZuordnung($student_uid, getAuthUID())->retval) > 0; - - if(getAuthUID() == $student_uid || $isZugeteilterBetreuer) { - $file_path = PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'; - if(file_exists($file_path)) { - - header('Content-Description: File Transfer'); - header('Content-Type: application/octet-stream'); - header('Expires: 0'); - header('Cache-Control: must-revalidate'); - header('Pragma: public'); - header('Content-Disposition: attachment; filename="'.basename($file_path).'"'); - header('Content-Length: ' . filesize($file_path)); - - flush(); // send headers first just in case - readfile($file_path); // read file content to output buffer - - } else { - $this->terminateWithJsonError('File not found'); - } + if(defined('CIS4') && CIS4) { + $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'DeadlinesOverview']); } else { - $this->terminateWithJsonError('Keine Zuordnung!'); + $this->load->view('Cis/Abgabetool.php', ['uid' => getAuthUID(), 'route' => 'DeadlinesOverview']); } } } diff --git a/application/controllers/Studentenverwaltung.php b/application/controllers/Studentenverwaltung.php index 3fba97e91..36c91d5f6 100644 --- a/application/controllers/Studentenverwaltung.php +++ b/application/controllers/Studentenverwaltung.php @@ -32,9 +32,9 @@ class Studentenverwaltung extends Auth_Controller 'student/keine_studstatuspruefung' => $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung'), 'lehre/reihungstestAufsicht' => $this->permissionlib->isBerechtigt('lehre/reihungstestAufsicht'), 'system/change_outputformat' => $this->permissionlib->getOE_isEntitledFor('system/change_outputformat'), - 'student/editBakkZgv' => $this->permissionlib->isBerechtigt('student/editBakkZgv'), - 'student/editMakkZgv' => $this->permissionlib->isBerechtigt('student/editMakkZgv'), - 'student/editDokZgv' => $this->permissionlib->isBerechtigt('student/editDokZgv'), + 'student/editBakkZgv' => $this->permissionlib->getSTG_isEntitledFor('student/editBakkZgv') ?: array(), + 'student/editMakkZgv' => $this->permissionlib->getSTG_isEntitledFor('student/editMakkZgv') ?: array(), + 'student/editDokZgv' => $this->permissionlib->getSTG_isEntitledFor('student/editDokZgv') ?: array(), 'student/editBismelden' => $this->permissionlib->isBerechtigt('student/editBismelden') ], 'variables' => [ diff --git a/application/controllers/api/frontend/v1/Abgabe.php b/application/controllers/api/frontend/v1/Abgabe.php new file mode 100644 index 000000000..5a6331584 --- /dev/null +++ b/application/controllers/api/frontend/v1/Abgabe.php @@ -0,0 +1,1295 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +use CI3_Events as Events; + +class Abgabe extends FHCAPI_Controller +{ + + /** + * Object initialization + */ + public function __construct() + { + parent::__construct([ + 'getConfig' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_lektor:rw'), + 'getConfigStudent' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_student:rw', 'basis/abgabe_lektor:rw'), + 'getStudentProjektarbeiten' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_student:rw', 'basis/abgabe_lektor:rw'), + 'getStudentProjektabgaben' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_student:rw', 'basis/abgabe_lektor:rw'), + 'postStudentProjektarbeitZwischenabgabe' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_student:rw'), + 'postStudentProjektarbeitEndupload' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_student:rw'), + 'getMitarbeiterProjektarbeiten' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_lektor:rw'), + 'postProjektarbeitAbgabe' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_lektor:rw'), + 'deleteProjektarbeitAbgabe' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_lektor:rw'), + 'postSerientermin' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_lektor:rw'), + 'fetchDeadlines' => array('basis/abgabe_assistenz:rw', 'basis/abgabe_lektor:rw'), + 'getPaAbgabetypen' => self::PERM_LOGGED, + 'getNoten' => self::PERM_LOGGED, + 'getProjektarbeitenForStudiengang' =>array('basis/abgabe_assistenz:rw'), + 'getStudiengaenge' => array('basis/abgabe_assistenz:rw'), + 'getStudentProjektarbeitAbgabeFile' => array('basis/abgabe_student:rw', 'basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw'), + 'postStudentProjektarbeitZusatzdaten' => array('basis/abgabe_lektor:rw', 'basis/abgabe_assistenz:rw') + ]); + + $this->load->library('PhrasesLib'); + $this->load->library('SignatureLib'); + + // Loads LogLib with different debug trace levels to get data of the job that extends this class + // It also specify parameters to set database fields + $this->load->library('LogLib', array( + 'classIndex' => 5, + 'functionIndex' => 5, + 'lineIndex' => 4, + 'dbLogType' => 'API', // required + 'dbExecuteUser' => 'RESTful API', + 'requestId' => 'API', + 'requestDataFormatter' => function ($data) { + return json_encode($data); + } + ), 'logLib'); + + $this->loadPhrases( + array( + 'global', + 'ui', + 'abgabetool' + ) + ); + $this->load->config('abgabe'); + $this->load->helper('hlp_sancho_helper'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * loads config related to abgabetool, found in application/config/abgabe + */ + public function getConfig() { + $old_abgabe_beurteilung_link =$this->config->item('old_abgabe_beurteilung_link'); + $turnitin_link = $this->config->item('turnitin_link'); + $abgabetypenBetreuer = $this->config->item('ALLOWED_ABGABETYPEN_BETREUER'); + + $ret = array( + 'old_abgabe_beurteilung_link' => $old_abgabe_beurteilung_link, + 'turnitin_link' => $turnitin_link, + 'abgabetypenBetreuer' => $abgabetypenBetreuer + ); + + $this->terminateWithSuccess($ret); + } + + /** + * loads config related to abgabetool for students to avoid handing out links reserved for employees + */ + public function getConfigStudent() { + $moodle_link =$this->config->item('STG_MOODLE_LINK'); + + $ret = array( + 'moodle_link' => $moodle_link, + ); + + $this->terminateWithSuccess($ret); + } + + /** + * fetches all projektabgabetermine for a given projektarbeit_id used in cis4 student abgabetool & lektor abgabetool + */ + public function getStudentProjektabgaben() { + $projektarbeit_id = $this->input->get("projektarbeit_id",TRUE); + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + if ($projektarbeit_id === NULL || trim((string)$projektarbeit_id) === '') { + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + + $result = $this->ProjektarbeitModel->load($projektarbeit_id); + $projektarbeitArr = $this->getDataOrTerminateWithError($result, 'general'); + + if(count($projektarbeitArr) > 0) { + $projektarbeit = $projektarbeitArr[0]; + } else { + $this->terminateWithError($this->p->t('abgabetool','c4projektarbeitNichtGefunden'), 'general'); + } + + $res = $this->ProjektarbeitModel->getStudentInfoForProjektarbeitId($projektarbeit_id); + if(isError($res)) { + $this->terminateWithError($this->p->t('abgabetool', 'c4errorLoadingStudentForProjektarbeitID'), 'general'); + } + + if(!hasData($res)) { + $this->terminateWithError($this->p->t('abgabetool', 'c4noAssignedStudentForProjektarbeitID'), 'general'); + } + $data = getData($res)[0]; + $student_uid = $data->uid; + + $zugeordnet = $this->checkZuordnung($projektarbeit_id, getAuthUID()); + if(getAuthUID() == $student_uid || $zugeordnet) { + $projektarbeitIsCurrent = false; + $returnFunc = function ($result) use (&$projektarbeitIsCurrent) { + $projektarbeitIsCurrent = $result; + }; + Events::trigger('projektarbeit_is_current', $projektarbeit_id, $returnFunc); + + $ret = $this->ProjektarbeitModel->getProjektarbeitAbgabetermine($projektarbeit_id); + + foreach ($ret->retval as $termin) { + $this->checkAbgabeSignatur($termin, $projektarbeit); + } + + $this->terminateWithSuccess(array($ret, $projektarbeitIsCurrent)); + } + } + + /** + * fetches all projektarbeiten and betreuer for a given student_uid used in cis4 student abgabetool + */ + public function getStudentProjektarbeiten() + { + $uid = $this->input->get("uid",TRUE); + + $this->load->model('person/Person_model', 'PersonModel'); + $this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel'); + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + // if uid is missing or empty, fall back to getAuthUID() + if ($uid === NULL || trim((string)$uid) === '') { + $uid = getAuthUID(); + } + + $isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID()); + if ($isMitarbeiter) { + $result = $this->ProjektarbeitModel->getStudentProjektarbeitenWithBetreuer($uid); + } else { + $result = $this->ProjektarbeitModel->getStudentProjektarbeitenWithBetreuer(getAuthUID()); + } + + $projektarbeiten = getData($result); + + if(count($projektarbeiten)) { + foreach($projektarbeiten as $pa) { + + $pa->student = getData($this->PersonModel->getFullName($uid)); + + $downloadPaFunc = function ($babgeschickt, $zweitbetreuer_abgeschickt) use ($pa) { + $pa->babgeschickt = $babgeschickt; + $pa->zweitbetreuer_abgeschickt = $zweitbetreuer_abgeschickt; + }; + + Events::trigger('projektbeurteilung_check_available', $pa->projektarbeit_id, $pa->bperson_id, $downloadPaFunc); + + if(isset($pa->babgeschickt) && $pa->babgeschickt) { + $downloadLink1 = ''; + $downloadLinkFunc1 = function ($link) use (&$downloadLink1) { + $downloadLink1 = $link; + }; + + Events::trigger('projektbeurteilung_download_link', $pa->projektarbeit_id, $pa->betreuerart_kurzbz, $pa->bperson_id, $downloadLinkFunc1); + + // use config fallback in case the event fails + if($downloadLink1 == '') { + $fallback = $this->config->item('beurteilung_link_fallback'); + + $search = array( + 'betreuerart_kurzbz=?', + 'projektarbeit_id=?', + 'person_id=?' + ); + + $replace = array( + 'betreuerart_kurzbz=' . $pa->betreuerart_kurzbz, + 'projektarbeit_id=' . $pa->projektarbeit_id, + 'person_id=' . $pa->bperson_id + ); + + $fallback = str_replace($search, $replace, $fallback); + $downloadLink1 = APP_ROOT.$fallback; + + } + $pa->downloadLink1 = $downloadLink1; + } + + $pa->email = $pa->mitarbeiter_uid.'@'.DOMAIN; + + if($pa->zweitbetreuer_person_id !== null) { + + if($pa->zweitbetreuer_abgeschickt) { + $downloadLink2 = ''; + $downloadLinkFunc2 = function ($link) use (&$downloadLink2) { + $downloadLink2 = $link; + }; + + Events::trigger('projektbeurteilung_download_link', $pa->projektarbeit_id, $pa->zweitbetreuer_betreuerart_kurzbz, $pa->zweitbetreuer_person_id, $downloadLinkFunc2); + + // use config fallback in case the event fails + if($downloadLink2 == '') { + $fallback = $this->config->item('beurteilung_link_fallback'); + + $search = array( + 'betreuerart_kurzbz=?', + 'projektarbeit_id=?', + 'person_id=?' + ); + + $replace = array( + 'betreuerart_kurzbz=' . $pa->zweitbetreuer_betreuerart_kurzbz, + 'projektarbeit_id=' . $pa->projektarbeit_id, + 'person_id=' . $pa->zweitbetreuer_person_id + ); + + $fallback = str_replace($search, $replace, $fallback); + $downloadLink2 = APP_ROOT.$fallback; + + } + + $pa->downloadLink2 = $downloadLink2; + } + + $result = $this->ProjektarbeitModel->getProjektbetreuerAnrede($pa->zweitbetreuer_person_id); + + $data = getData($result); + if(count($data) > 0) { + $pa->zweitbetreuer = $data[0]; + } + } + } + } + + $this->terminateWithSuccess(array($projektarbeiten)); + } + + + + /** + * projektarbeit - upload for zwischenabgaben in cis4 student abgabetool + */ + public function postStudentProjektarbeitZwischenabgabe() + { + $this->checkUploadSize(); + + $projektarbeit_id = $this->input->post('projektarbeit_id'); + $paabgabe_id = $this->input->post('paabgabe_id'); + $student_uid = $this->input->post('student_uid'); + $bperson_id = $this->input->post('bperson_id'); + $paabgabetyp_kurzbz = $this->input->post('paabgabetyp_kurzbz'); + + if ($projektarbeit_id === NULL || trim((string)$projektarbeit_id) === '' + || $paabgabe_id === NULL || trim((string)$paabgabe_id) === '' + || $student_uid === NULL || trim((string)$student_uid) === '' + || $paabgabetyp_kurzbz === NULL || trim((string)$paabgabetyp_kurzbz) === '') { + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + + $this->checkProjektarbeitForFinishedStatus($projektarbeit_id); + + $zugeordnet = $this->checkZuordnung($projektarbeit_id, getAuthUID()); + if(getAuthUID() == $student_uid || $zugeordnet) { + + + $path = PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'; + + if ((isset($_FILES) and isset($_FILES['file']) and ! $_FILES['file']['error'])) { + move_uploaded_file($_FILES['file']['tmp_name'], $path); + + if(file_exists($path)) { + + chmod($path, 0640); + + $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->logLib->logInfoDB(array('zwischenupload',$res, array( + 'abgabedatum' => date('Y-m-d'), + 'updatevon' => getAuthUID(), + 'updateamum' => date('Y-m-d H:i:s') + ), getAuthUID(), getAuthPersonId(), $student_uid)); + + $this->terminateWithSuccess($res); + } else { + $this->terminateWithError('Error moving File', 'general'); + } + + } else { + $this->terminateWithError('File missing', 'general'); + } + } else { + $this->terminateWithError($this->p->t('abgabetool', 'c4noZuordnungBetreuerStudent')); + } + +} + + /** + * upload für finale abgaben aka Endupload in cis4 student abgabetool + */ + public function postStudentProjektarbeitEndupload() + { + $this->checkUploadSize(); + + $projektarbeit_id = $this->input->post('projektarbeit_id'); + $paabgabe_id = $this->input->post('paabgabe_id'); + $student_uid = $this->input->post('student_uid'); + $sprache = $this->input->post('sprache'); + $abstract = $this->input->post('abstract'); + $abstract_en = $this->input->post('abstract_en'); + $schlagwoerter = $this->input->post('schlagwoerter'); + $schlagwoerter_en = $this->input->post('schlagwoerter_en'); + $seitenanzahl = $this->input->post('seitenanzahl'); + $bperson_id = $this->input->post('bperson_id'); + $paabgabetyp_kurzbz = $this->input->post('paabgabetyp_kurzbz'); + + if ($projektarbeit_id === NULL || trim((string)$projektarbeit_id) === '' + || $paabgabe_id === NULL || trim((string)$paabgabe_id) === '' + || $student_uid === NULL || trim((string)$student_uid) === '' + || $paabgabetyp_kurzbz === NULL || trim((string)$paabgabetyp_kurzbz) === '' + || $abstract === NULL || $abstract_en === NULL + || $schlagwoerter === NULL || $schlagwoerter_en === NULL + || $seitenanzahl === NULL || $sprache === NULL) { + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + + $this->checkProjektarbeitForFinishedStatus($projektarbeit_id); + + $zugeordnet = $this->checkZuordnung($projektarbeit_id, getAuthUID()); + if(getAuthUID() == $student_uid || $zugeordnet) { + 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')) { + + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $result = $this->ProjektarbeitModel->load($projektarbeit_id); + $projektarbeitArr = $this->getDataOrTerminateWithError($result, 'general'); + + if (count($projektarbeitArr) > 0) { + $projektarbeit = $projektarbeitArr[0]; + } else { + $this->terminateWithError($this->p->t('abgabetool', 'c4projektarbeitNichtGefunden'), 'general'); + } + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $result = $this->PaabgabeModel->load($paabgabe_id); + $paabgabeArr = $this->getDataOrTerminateWithError($result, 'general'); + + if (count($paabgabeArr) > 0) { + $paabgabe = $paabgabeArr[0]; + } else { + $this->terminateWithError($this->p->t('abgabetool', 'c4projektabgabeNichtGefunden'), 'general'); + } + + $this->checkAbgabeSignatur($paabgabe, $projektarbeit); + $signaturstatus = $paabgabe->signatur; + + // update projektarbeit cols + $this->ProjektarbeitModel->updateProjektarbeit($projektarbeit_id, $sprache, $abstract, $abstract_en + , $schlagwoerter, $schlagwoerter_en, $seitenanzahl); + + + // update paabgabe datum + $res = $this->PaabgabeModel->update($paabgabe_id, array( + 'abgabedatum' => date('Y-m-d'), + 'updatevon' => getAuthUID(), + 'updateamum' => date('Y-m-d H:i:s') + )); + + $res = $this->PaabgabeModel->load($res->retval); + $abgabe = getData($res)[0]; + $abgabe->signatur = $signaturstatus; + + $this->sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid); + + $this->logLib->logInfoDB(array('endupload', $res, array( + 'abgabedatum' => date('Y-m-d'), + 'updatevon' => getAuthUID(), + 'updateamum' => date('Y-m-d H:i:s') + ), getAuthUID(), getAuthPersonId(), array($projektarbeit_id, $sprache, $abstract, $abstract_en + , $schlagwoerter, $schlagwoerter_en, $seitenanzahl))); + + $this->terminateWithSuccess($abgabe); + } else { + $this->terminateWithError('Error moving File', 'general'); + } + + } else { + $this->terminateWithError('File missing', 'general'); + } + } else { + $this->terminateWithError($this->p->t('abgabetool', 'c4noZuordnungBetreuerStudent')); + } + + } + + /** + * tabulator tabledata fetch for abgabetool/mitarbeiter + * initially fetches all currently active projektarbeiten with assigned mentorship + * showAll functionality also retrieves older finished projektarbeiten + */ + 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); + + $showAllBool = false; // fallback if input strings are anything else for whatever reason + if (in_array($boolParamStrLower, $trueStrings, true)) { + $showAllBool = true; + } elseif (in_array($boolParamStrLower, $falseStrings, true)) { + $showAllBool = false; + } + + $projektarbeiten = $this->ProjektarbeitModel->getMitarbeiterProjektarbeiten(getAuthUID(), $showAllBool); + + + forEach($projektarbeiten->retval as $pa) { + + $result = $this->ProjektarbeitModel->getProjektbetreuerAnrede($pa->betreuer_person_id); + $anredeArr = $this->getDataOrTerminateWithError($result, 'general'); + $pa->betreuer = $anredeArr[0]; + + $oldLink = ''; // show this when paIsCurrent == false -> moodle course template + $newLink = ''; // get curated path for betreuer type + $returnFunc = function ( $resultOld, $resultNew) use (&$oldLink, &$newLink) { + $newLink = $resultNew; + $oldLink = $resultOld; + }; + + Events::trigger('projektbeurteilung_formular_link', $pa->betreuerart_kurzbz, APP_ROOT, $pa->projektarbeit_id, $pa->student_uid, $returnFunc); + $pa->beurteilungLinkNew = $newLink; + $pa->beurteilungLinkOld = $oldLink; + } + + + $this->terminateWithSuccess(array($projektarbeiten, DOMAIN)); + } + + /** + * called by abgabetool/mitarbeiter in mitarbeiterdetail.js when adding a single new abgabetermin + * initially fetches all + */ + public function postProjektarbeitAbgabe() { + $projektarbeit_id = $this->input->post('projektarbeit_id'); + $paabgabe_id = $this->input->post('paabgabe_id'); + $paabgabetyp_kurzbz = $this->input->post('paabgabetyp_kurzbz'); + $datum = $this->input->post('datum'); + $fixtermin = $this->input->post('fixtermin'); + $kurzbz = $this->input->post('kurzbz'); + $note = $this->input->post('note'); + $beurteilungsnotiz = $this->input->post('beurteilungsnotiz'); + $upload_allowed = $this->input->post('upload_allowed'); + $betreuer_person_id = $this->input->post('betreuer_person_id'); + + if ($projektarbeit_id === NULL || trim((string)$projektarbeit_id) === '' + || $paabgabe_id === NULL || trim((string)$paabgabe_id) === '' + || $datum === NULL || trim((string)$datum) === '' + || $kurzbz === NULL + || $paabgabetyp_kurzbz === NULL || trim((string)$paabgabetyp_kurzbz) === '') { + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + + $this->checkProjektarbeitForFinishedStatus($projektarbeit_id); + + $zugeordnet = $this->checkZuordnung($projektarbeit_id, getAuthUID()); + if(!$zugeordnet) { + $this->terminateWithError($this->p->t('abgabetool', 'c4noZuordnungBetreuerStudent')); + } + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + + $existingPaabgabe = null; + if($paabgabe_id == -1) { + $result = $this->PaabgabeModel->insert( + array( + 'projektarbeit_id' => $projektarbeit_id, + 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, + 'fixtermin' => $fixtermin, + 'datum' => $datum, + 'kurzbz' => $kurzbz, + 'note' => $note, + 'beurteilungsnotiz' => $beurteilungsnotiz, + 'upload_allowed' => $upload_allowed, + 'insertvon' => getAuthUID(), + 'insertamum' => date('Y-m-d H:i:s') + ) + ); + $this->logLib->logInfoDB(array('paabgabe created',$result, getAuthUID(), getAuthPersonId())); + } else { + // load existing entry of paabgabe and check if note has changed to negativ, to avoid sending when + // only notiz has changed. + + // TODO: what if paabgabe is a qualgate1, is benotet negativ and then its type is changed to gate2? + + $existingResult = $this->PaabgabeModel->load($paabgabe_id); + $existingPaabgabeArr = getData($existingResult); + if(count($existingPaabgabeArr) > 0) $existingPaabgabe = $existingPaabgabeArr[0]; + + $result = $this->PaabgabeModel->update( + $paabgabe_id, + array( + 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, + 'datum' => $datum, + 'kurzbz' => $kurzbz, + 'note' => $note, + 'fixtermin' => $fixtermin, + 'beurteilungsnotiz' => $beurteilungsnotiz, + 'upload_allowed' => $upload_allowed, + 'updatevon' => getAuthUID(), + 'updateamum' => date('Y-m-d H:i:s') + ) + ); + + $this->logLib->logInfoDB(array('paabgabe updated',$result, array( + 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, + 'datum' => $datum, + 'kurzbz' => $kurzbz, + 'note' => $note, + 'fixtermin' => $fixtermin, + 'beurteilungsnotiz' => $beurteilungsnotiz, + 'upload_allowed' => $upload_allowed, + 'updatevon' => getAuthUID(), + 'updateamum' => date('Y-m-d H:i:s') + ), getAuthUID(), getAuthPersonId())); + } + + // 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, 'general'); + + $result = $this->PaabgabeModel->load($paabgabe_id); + $paabgabeArr = $this->getDataOrTerminateWithError($result, 'general'); + $paabgabe = $paabgabeArr[0]; + + // 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, 'general'); + $note = $noteArr[0]; + if($note->positiv === false) { + + if($existingPaabgabe && $existingPaabgabe->note) { + $result = $this->NoteModel->load($paabgabe->note); + $noteArr = $this->getDataOrTerminateWithError($result, 'general'); + $note = $noteArr[0]; + if($note->positiv === false) { + // do nothing since this means $beurteilungsnotiz change or smth else + } else { // benotung legitimately changed -> email + $this->sendQualGateNegativEmail($projektarbeit_id, $betreuer_person_id, $paabgabe); + } + } else { // nothing existing previously -> send that mail + $this->sendQualGateNegativEmail($projektarbeit_id, $betreuer_person_id, $paabgabe); + } + + } + } + + $this->terminateWithSuccess([$paabgabe, $existingPaabgabe]); + } + + /** + * called by abgabetool/mitarbeiter in mitarbeiterdetail.js when deleting an abgabetermin + * deletion is only possible if user is assistenz OR betreuer deletes their own custom termin + * none of these roles are allowed to delete if students uploaded something for that termin + */ + public function deleteProjektarbeitAbgabe() { + $paabgabe_id = $this->input->post('paabgabe_id'); + + if ($paabgabe_id === NULL || trim((string)$paabgabe_id) === '') { + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + + $this->checkProjektarbeitForFinishedStatus($this->getProjektarbeitIDForPaabgabeID($paabgabe_id)); + + $zugeordnet = $this->checkZuordnungByPaabgabe($paabgabe_id, getAuthUID()); + + if(!$zugeordnet) { + $this->terminateWithError($this->p->t('abgabetool', 'c4noZuordnungBetreuerStudent'), 'general'); + } + + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + + $paabgabeResult = $this->PaabgabeModel->load($paabgabe_id); + $paabgabeArr = $this->getDataOrTerminateWithError($paabgabeResult, 'general'); + + if(count($paabgabeArr) == 0) { + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + + $result = $this->PaabgabeModel->delete($paabgabe_id); + $result = $this->getDataOrTerminateWithError($result, 'general'); + + // TODO: consider this in nightly email job + $this->logLib->logInfoDB(array($paabgabeArr[0], getAuthUID(), getAuthPersonId())); + $this->terminateWithSuccess($result); + } + + /** + * 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 = $this->input->post('projektarbeit_ids'); + $datum = $this->input->post('datum'); + $paabgabetyp_kurzbz = $this->input->post('paabgabetyp_kurzbz'); + $bezeichnung = $this->input->post('bezeichnung'); + $kurzbz = $this->input->post('kurzbz'); + $fixtermin = $this->input->post('fixtermin'); + $upload_allowed = $this->input->post('upload_allowed'); + + if ($projektarbeit_ids === NULL || !is_array($projektarbeit_ids) || empty($projektarbeit_ids) + || $datum === NULL || trim((string)$datum) === '' + || $kurzbz === NULL + || $bezeichnung === NULL || trim((string)$bezeichnung) === '' + || $paabgabetyp_kurzbz === NULL || trim((string)$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 + $this->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $res = []; + $abgaben = []; + foreach ($projektarbeit_ids as $projektarbeit_id) { + + $this->checkProjektarbeitForFinishedStatus($projektarbeit_id); + + $zugeordnet = $this->checkZuordnung($projektarbeit_id, getAuthUID()); + if(!$zugeordnet) { + $this->terminateWithError($this->p->t('abgabetool', 'c4noZuordnungBetreuerStudent'), 'general'); + } + + $result = $this->PaabgabeModel->insert( + array( + 'projektarbeit_id' => $projektarbeit_id, + 'paabgabetyp_kurzbz' => $paabgabetyp_kurzbz, + 'fixtermin' => $fixtermin, + 'datum' => $datum, + 'kurzbz' => $kurzbz, + 'upload_allowed' => $upload_allowed, + 'insertvon' => getAuthUID(), + 'insertamum' => date('Y-m-d H:i:s') + ) + ); + + $dataAbgabe = $this->getDataOrTerminateWithError($result, 'general'); + + $abgaben[]= getData($this->PaabgabeModel->load($dataAbgabe))[0]; + } + + $this->logLib->logInfoDB(array('serientermin angelegt',$res, getAuthUID(), getAuthPersonId())); + + $this->terminateWithSuccess($abgaben); + } + + /** + * called by Abgabetool/Deadlines + * fetches the next upcoming abgabtermine for a given betreuer person_id + * resembles the legacy abgabetool functionality of "show deadlines" + */ + public function fetchDeadlines() { + $person_id = $this->input->post('person_id'); + + if ($person_id === NULL || trim((string)$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, 'general'); + + $this->terminateWithSuccess($data); + } + + /** + * called by Abgabetool/Mitarbeiter & Abgabetool/Assistenz + * fetches all available paabgabetypen to enable a logical selection of them + * based on active status and role assistenz/betreuer + */ + public function getPaAbgabetypen() { + $this->load->model('education/Paabgabetyp_model', 'PaabgabetypModel'); + + $result = $this->PaabgabetypModel->getAll(); + $paabgabetypen = $this->getDataOrTerminateWithError($result, 'general'); + + + $this->terminateWithSuccess($paabgabetypen); + } + + /** + * helper function to fetch the correct email for a projektarbeits erstbetreuer + */ + private function getProjektbetreuerEmail($projektarbeit_id) { + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $result = $this->ProjektarbeitModel->getProjektbetreuerEmail($projektarbeit_id); + $email = $this->getDataOrTerminateWithError($result, 'general'); + + return $email[0]->uid ? $email[0]->uid.'@'.DOMAIN : $email[0]->private_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, 'general'); + + $allowed_noten_abgabetool = $this->config->item('ALLOWED_NOTEN_ABGABETOOL'); + + $this->terminateWithSuccess(array($noten, $allowed_noten_abgabetool)); + } + + /** + * helper function to send a sancho mail to students if a betreuer or assistenz grades a quality gate + * termin as negative (nicht bestanden) + */ + 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, 'general'); + $projektarbeit = $projektarbeitArr[0]; + + $result = $this->ProjektarbeitModel->getProjektbetreuerAnrede($betreuer_person_id); + $anredeArr = $this->getDataOrTerminateWithError($result, 'general'); + $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, 'general'); + $paabgabetyp_kurzbz = $paabgabetyp_kurzbzArr[0]; + + // Mail an Student wenn Qualgate negativ beurteilt wurde + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->load([$student_uid]); + $studentArr = $this->getDataOrTerminateWithError($result, 'general'); + $student = $studentArr[0]; + + if(!$student) { + $this->terminateWithError($this->p->t('abgabetool','c4userNichtGefunden'), 'general'); + } + + $subject = $this->p->t('abgabetool', 'c4qualgateNegativEmailSubjectv2'); + $tomail = $student_uid.'@'.DOMAIN; + + $datetime = new DateTime($paabgabe->datum); + $dateEmailFormatted = $datetime->format('d.m.Y'); + + $data = array( + 'betreuerfullname' => $anrede->first, + 'qualgatebezeichnung' => $paabgabetyp_kurzbz->bezeichnung, + 'datum' => $dateEmailFormatted, + 'projektarbeitname' => $projektarbeit->titel + ); + + // students still get theirs on event, since it is very unlikely that this + // leads to spam on their end + + $mailres = sendSanchoMail( + 'QualGateNegativ', + $data, + $tomail, + $subject + ); + + } + + /** + * tabulator tabledata fetch for abgabetool/assistenz + * initially fetches all ungraded projektarbeiten with all their abgabetermine + */ + public function getProjektarbeitenForStudiengang() { + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $studiengang_kz = $this->input->get("studiengang_kz", TRUE); + $benotet = $this->input->get("benotet", TRUE); + + if ($studiengang_kz === NULL || trim((string)$studiengang_kz) === '') { + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + + // TODO: recheck getSTGEntitlement here! + $stg_allowed = $this->permissionlib->getSTG_isEntitledFor('basis/abgabe_assistenz:rw'); + if($stg_allowed == false) { + $this->terminateWithError($this->p->t('ui', 'keineBerechtigung'), 'general'); + } + + // check if provided studiengang_kz is included in stg_allowed to proceed + if(!in_array($studiengang_kz, $stg_allowed)) { + $this->terminateWithError($this->p->t('ui', 'keineBerechtigung'), 'general'); + } + + $result = $this->ProjektarbeitModel->getProjektarbeitenForStudiengang($studiengang_kz, $benotet); + $projektarbeiten = $this->getDataOrTerminateWithError($result, 'general'); + + if(count($projektarbeiten) == 0) { // avoid further abgabetermin queries if the are no projektarbeiten + $this->terminateWithSuccess(array($projektarbeiten, DOMAIN)); + } + + $mapFunc = function($projektarbeit) { + return $projektarbeit->projektarbeit_id; + }; + $projektarbeiten_ids = array_map($mapFunc, $projektarbeiten); + + $ret = $this->ProjektarbeitModel->getProjektarbeitenAbgabetermine($projektarbeiten_ids); + $projektabgaben = $this->getDataOrTerminateWithError($ret, 'general'); + + // map the abgaben into projektarbeiten + foreach($projektarbeiten as $projektarbeit) { + $filterFunc = function($projektabgabe) use ($projektarbeit) { + return $projektabgabe->projektarbeit_id == $projektarbeit->projektarbeit_id; + }; + + $projektarbeit->abgabetermine = array_values(array_filter($projektabgaben, $filterFunc)); + + // check the signature status for enduploads + foreach($projektarbeit->abgabetermine as $abgabe) { + $this->checkAbgabeSignatur($abgabe, $projektarbeit); + } + } + + $this->terminateWithSuccess(array($projektarbeiten, DOMAIN)); + } + + // TODO: this could be in a generic info controller and reused + /** + * GET METHOD + * returns List of all studiengang_kz a user has the assigned permission 'basis/abgabe_assistenz:rw' for + * used in Abgabetool/Assistenz to populate Studiengang Dropdown + */ + public function getStudiengaenge() { + $this->load->library('PermissionLib'); + + $stg_allowed = $this->permissionlib->getSTG_isEntitledFor('basis/abgabe_assistenz:rw'); + + if($stg_allowed == false) { + $this->terminateWithError($this->p->t('ui', 'keineBerechtigung'), 'general'); + } + + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + + $result = $this->StudiengangModel->getStudiengaengeFiltered($stg_allowed); + $data = $this->getDataOrTerminateWithError($result, 'general'); + + $this->terminateWithSuccess($data); + } + + /** + * GET METHOD + * endpoint to download the abgabe of a paabgabe termin zwischenabgabe or endupload + */ + public function getStudentProjektarbeitAbgabeFile() + { + $this->load->helper('download'); + + $projektarbeit_id = $this->input->get('projektarbeit_id'); + $paabgabe_id = $this->input->get('paabgabe_id'); + $student_uid = $this->input->get('student_uid'); + + if ($paabgabe_id === NULL || trim((string)$paabgabe_id) === '' + || $projektarbeit_id === NULL || trim((string)$projektarbeit_id) === '' + || $student_uid === NULL || trim((string)$student_uid) === '') { + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + // zuordnung function is supposed for mitarbeiter_uids, students should be allowed to download their own files + // without adapting zuordnung logic + $zugeordnet = $this->checkZuordnung($projektarbeit_id, getAuthUID()); + if(getAuthUID() == $student_uid || $zugeordnet) { + $file_path = PAABGABE_PATH.$paabgabe_id.'_'.$student_uid.'.pdf'; + + + if(file_exists($file_path)) { + $this->terminateWithFileOutput('application/octet-stream', file_get_contents($file_path), basename($file_path)); + } else { + $this->terminateWithError('File not found', 'general'); + } + } else { + $this->terminateWithError($this->p->t('abgabetool', 'c4noZuordnungBetreuerStudent'), 'general'); + } + } + + /** + * POST METHOD + * endpoint to enable Assistenz/Betreuer to edit the zusatzdate of a projektarbeit, in case the student somehow + * can't do it themself + */ + public function postStudentProjektarbeitZusatzdaten(){ + $projektarbeit_id = $this->input->post('projektarbeit_id'); + $sprache = $this->input->post('sprache'); + $abstract = $this->input->post('abstract'); + $abstract_en = $this->input->post('abstract_en'); + $schlagwoerter = $this->input->post('schlagwoerter'); + $schlagwoerter_en = $this->input->post('schlagwoerter_en'); + $seitenanzahl = $this->input->post('seitenanzahl'); + + if ($projektarbeit_id === NULL || trim((string)$projektarbeit_id) === '' + || $sprache === NULL || trim((string)$sprache) === '' + || $seitenanzahl === NULL || trim((string)$seitenanzahl) === '' + || $abstract === NULL || trim((string)$abstract) === '' + || $abstract_en === NULL || trim((string)$abstract_en) === '' + || $schlagwoerter === NULL || trim((string)$schlagwoerter) === '' + || $schlagwoerter_en === NULL || trim((string)$schlagwoerter_en) === '') { + + $this->terminateWithError($this->p->t('global', 'wrongParameters'), 'general'); + } + + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + + + $result = $this->ProjektarbeitModel->load($projektarbeit_id); + $projektarbeitArr = $this->getDataOrTerminateWithError($result, 'general'); + + if(count($projektarbeitArr) > 0) { + $projektarbeit = $projektarbeitArr[0]; + } else { + $this->terminateWithError($this->p->t('abgabetool','c4projektarbeitNichtGefunden'), 'general'); + } + + $this->checkProjektarbeitForFinishedStatus($projektarbeit_id); + + $zugeordnet = $this->checkZuordnung($projektarbeit_id, getAuthUID()); + if(!$zugeordnet) { + $this->terminateWithError($this->p->t('abgabetool', 'c4noZuordnungBetreuerStudent'), 'general'); + } + + // update projektarbeit cols + $this->ProjektarbeitModel->updateProjektarbeit($projektarbeit_id,$sprache,$abstract,$abstract_en + ,$schlagwoerter, $schlagwoerter_en, $seitenanzahl); + + $this->logLib->logInfoDB(array('zusatzdatenEditMitarbeiter', array( + 'updatevon' => getAuthUID(), + 'updateamum' => date('Y-m-d H:i:s') + ), getAuthUID(), getAuthPersonId(), array($projektarbeit_id,$sprache,$abstract,$abstract_en + ,$schlagwoerter, $schlagwoerter_en, $seitenanzahl))); + + $result = $this->ProjektarbeitModel->load($projektarbeit_id); + + $this->terminateWithSuccess($result); + } + + /** + * helper function to check the signature status of uploaded files for zwischenabgabe & endupload + */ + private function checkAbgabeSignatur($abgabe, $projektarbeit) { + $paabgabetypenToCheck = $this->config->item('SIGNATUR_CHECK_PAABGABETYPEN'); + + if(!in_array($abgabe->paabgabetyp_kurzbz, $paabgabetypenToCheck)) { + return; + } + + if (!defined('SIGNATUR_URL')) { + $abgabe->signatur = 'error'; + return; + } + + $path = PAABGABE_PATH.$abgabe->paabgabe_id.'_'.$projektarbeit->student_uid.'.pdf'; + + $signaturVorhanden = null; // if frontend receives null -> indicates no file found at path + if(file_exists($path)) { + + // Check if the document is signed + $signList = SignatureLib::list($path); + if (is_array($signList) && count($signList) > 0) + { + // The document is signed + $signaturVorhanden = true; + } + elseif ($signList === null) + { + // frontend knows to handle it this way for signatures + $signaturVorhanden = 'error'; + } + else + { + $signaturVorhanden = false; + } + + $abgabe->signatur = $signaturVorhanden; + } + } + + private function sendUploadEmail($bperson_id, $projektarbeit_id, $paabgabetyp_kurzbz, $student_uid) { + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $resBetr = $this->ProjektarbeitModel->getProjektbetreuerAnrede($bperson_id); + + + $result = $this->ProjektarbeitModel->load($projektarbeit_id); + $projektarbeitArr = $this->getDataOrTerminateWithError($result, 'general'); + + if(count($projektarbeitArr) > 0) { + $projektarbeit = $projektarbeitArr[0]; + } else { + $this->terminateWithError($this->p->t('abgabetool','c4projektarbeitNichtGefunden'), 'general'); + } + + $projektarbeitIsCurrent = false; + $returnFunc = function ($result) use (&$projektarbeitIsCurrent) { + $projektarbeitIsCurrent = $result; + }; + Events::trigger('projektarbeit_is_current', $projektarbeit_id, $returnFunc); + if(!$projektarbeitIsCurrent) { + $this->terminateWithError($this->p->t('abgabetool','c4fehlerAktualitaetProjektarbeit'), 'general'); + } + + // Link to Abgabetool + if (defined('CIS4') && CIS4) { + $ci3BootstrapFilePath = "cis.php"; + } else { + $ci3BootstrapFilePath = "index.ci.php"; + } + + $path = $this->config->item('URL_MITARBEITER'); + $url = APP_ROOT.$path; + + // getProjektbetreuerAnrede fetches distinct on person_id, so there should be one row. zweitbetreuer is handled seperately afterwards + foreach($resBetr->retval as $betreuerRow) { + + // query student benutzer view for every betreuer row + $studentUser = $this->ProjektarbeitModel->getProjektarbeitBenutzer($student_uid)->retval[0]; + + // 1. Begutachter mail ohne Token + $mail_baselink = APP_ROOT.$this->config->item('PROJEKTARBEITSBEURTEILUNG_MAIL_BASELINK_ERSTBEGUTACHTER'); +// $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->projekttyp_kurzbz; + $subject = $projektarbeit->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'] = $projektarbeitIsCurrent && $paabgabetyp_kurzbz == 'end' ? "

Zur Beurteilung der Arbeit

" : ""; + $maildata['token'] = ""; + + $email = $this->getProjektbetreuerEmail($projektarbeit_id); + + if(!$email) $this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailBegutachter'), 'general'); + + $mailres = sendSanchoMail( + 'ParbeitsbeurteilungEndupload', + $maildata, + $email, + $subject, + 'sancho_header_min_bw.jpg', + 'sancho_footer_min_bw.jpg', + get_uid()."@".DOMAIN); + + if(!$mailres) + { + $this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailBegutachter'), 'general'); + } + + // 2. Begutachter mail, wenn Endabgabe, mit Token wenn extern + if ($paabgabetyp_kurzbz == 'end') + { + // Zweitbegutachter holen + $this->load->model('education/Projektbetreuer_model', 'ProjektbetreuerModel'); + $zweitbegutachterRetval = getData($this->ProjektbetreuerModel->getZweitbegutachterWithToken($bperson_id, $projektarbeit_id, $studentUser->uid)); + + if ($zweitbegutachterRetval && count($zweitbegutachterRetval) > 0) + { + + foreach ($zweitbegutachterRetval as $begutachter) + { + // token generieren, wenn noch nicht vorhanden und notwendig (wird in methode überprüft) + $tokenGenRes = $this->ProjektbetreuerModel->generateZweitbegutachterToken($begutachter->person_id, $projektarbeit_id); + + if (!$tokenGenRes) + { + $this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailZweitBegutachter'), 'general'); + } + + $begutachterMitTokenRetval = getData($this->ProjektbetreuerModel->getZweitbegutachterWithToken($bperson_id, $projektarbeit_id, $studentUser->uid, $begutachter->person_id)); + + if (!$begutachterMitTokenRetval && count($begutachterMitTokenRetval) <= 0) + { + $this->terminateWithError($this->p->t('abgabetool', 'c4fehlerMailZweitBegutachter'), 'general'); + } + + $begutachterMitToken = $begutachterMitTokenRetval[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'] = $projektarbeitIsCurrent ? "

Zur Beurteilung der Arbeit

" : ""; + $zweitbetmaildata['token'] = $projektarbeitIsCurrent && 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', 'c4fehlerMailBegutachter'), 'general'); + } + + } + } + } + } + } + + private function checkZuordnung($projektarbeit_id, $betreuer_uid) { + // check if authenticated user is zugewiesen as betreuer to projektarbeit or has admin/assistenz berechtigung + // over the studiengang of the student working on that projektarbeit_id + + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $res = $this->ProjektarbeitModel->getStudentInfoForProjektarbeitId($projektarbeit_id); + if(isError($res)) { + $this->terminateWithError($this->p->t('abgabetool', 'c4errorLoadingStudentForProjektarbeitID'), 'general'); + } + + if(!hasData($res)) { + $this->terminateWithError($this->p->t('abgabetool', 'c4noAssignedStudentForProjektarbeitID'), 'general'); + } + $data = getData($res)[0]; + $student_uid = $data->uid; + $studiengang_kz = $data->studiengang_kz; + + $res = $this->ProjektarbeitModel->checkZuordnung($student_uid, $betreuer_uid); + if(isError($res)) { + $this->terminateWithError($this->p->t('abgabetool', 'c4errorLoadingBetreuerStudentZuordnung'), 'general'); + } + + // if this is true betreuer has zuordnung to the given $projektarbeit_id and conversely the $student_uid + // assigned to that project + if(hasData($res)) { + return true; + } else { + $berechtigt = $this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id); + if($berechtigt) { + return true; + } + + // otherwhise if there is no zuordnung via global admin or assistenz berechtigung, + // check if the given uid has permissions over the studiengang of the student + // via the abgabetool specific berechtigungen + // 'basis/abgabe_assistenz:rw' OR 'basis/abgabe_lektor:rw' + + if ($this->permissionlib->isBerechtigt('basis/abgabe_assistenz', 'suid', $studiengang_kz)) { + return true; + } + + if ($this->permissionlib->isBerechtigt('basis/abgabe_lektor', 'suid', $studiengang_kz)){ + return true; + } + } + + return false; + } + + private function getProjektarbeitIDForPaabgabeID($paabgabe_id) { + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + + $res = $this->ProjektarbeitModel->getProjektarbeitByPaabgabeID($paabgabe_id); + if(isError($res)) { + $this->terminateWithError($this->p->t('abgabetool', 'c4errorLoadingProjektarbeitForPaabgabeID'), 'general'); + } + + if(!hasData($res)) { + $this->terminateWithError($this->p->t('abgabetool', 'c4noAssignedProjektarbeitForPaabgabeID'), 'general'); + } + $data = getData($res)[0]; + return $data->projektarbeit_id; + } + + private function checkZuordnungByPaabgabe($paabgabe_id, $betreuer_uid) { + $projektarbeit_id = $this->getProjektarbeitIDForPaabgabeID($paabgabe_id); + return $this->checkZuordnung($projektarbeit_id, $betreuer_uid); + } + + // loads a projektarbeit table row by id and looks if a note has been set. A non null note field + // currently indicates that a projektarbeit has been finished and should not accept further crud manipulation + private function checkProjektarbeitForFinishedStatus($projektarbeit_id) { + $this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $res = $this->ProjektarbeitModel->load($projektarbeit_id); + + if(isError($res) || !hasData($res)) { + $this->terminateWithError($this->p->t('abgabetool','c4projektarbeitNichtGefunden'), 'general'); + } + + $data = getData($res)[0]; + if($data->note !== NULL) { + $this->terminateWithError($this->p->t('abgabetool','c4fehlerAktualitaetProjektarbeit'), 'general'); + } + } + +} \ No newline at end of file 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/controllers/api/frontend/v1/lv/Setup.php b/application/controllers/api/frontend/v1/lv/Setup.php index a2c167dd6..eea4befa5 100644 --- a/application/controllers/api/frontend/v1/lv/Setup.php +++ b/application/controllers/api/frontend/v1/lv/Setup.php @@ -47,22 +47,22 @@ class Setup extends FHCAPI_Controller { $tabs['details'] = array ( 'title' => 'Details', - 'component' => APP_ROOT . 'public/js/components/LVVerwaltung/Tabs/Details.js', + 'component' => absoluteJsImportUrl('public/js/components/LVVerwaltung/Tabs/Details.js'), 'config' => [] ); $tabs['gruppen'] = array ( 'title' => 'Gruppen', - 'component' => APP_ROOT . 'public/js/components/LVVerwaltung/Tabs/Gruppen.js', + 'component' => absoluteJsImportUrl('public/js/components/LVVerwaltung/Tabs/Gruppen.js'), 'config' => [] ); $tabs['lektor'] = array ( 'title' => 'LektorInnenzuteilung', - 'component' => APP_ROOT . 'public/js/components/LVVerwaltung/Tabs/Lektor.js', + 'component' => absoluteJsImportUrl('public/js/components/LVVerwaltung/Tabs/Lektor.js'), 'config' => [] ); $tabs['notiz'] = array ( 'title' => 'Notizen', - 'component' => APP_ROOT . 'public/js/components/LVVerwaltung/Tabs/Notiz.js', + 'component' => absoluteJsImportUrl('public/js/components/LVVerwaltung/Tabs/Notiz.js'), 'config' => [] ); $this->terminateWithSuccess($tabs); diff --git a/application/controllers/api/frontend/v1/organisation/Studiensemester.php b/application/controllers/api/frontend/v1/organisation/Studiensemester.php index bb56ea71a..3c6b72d2f 100644 --- a/application/controllers/api/frontend/v1/organisation/Studiensemester.php +++ b/application/controllers/api/frontend/v1/organisation/Studiensemester.php @@ -25,7 +25,8 @@ class Studiensemester extends FHCAPI_Controller array( 'getAll' => self::PERM_LOGGED, 'getAktNext' => self::PERM_LOGGED, - 'getStudienjahrByStudiensemester' => self::PERM_LOGGED + 'getStudienjahrByStudiensemester' => self::PERM_LOGGED, + 'getAllStudiensemesterAndAktOrNext' => self::PERM_LOGGED ) ); // Load model StudiensemesterModel @@ -152,4 +153,17 @@ class Studiensemester extends FHCAPI_Controller $this->terminateWithSuccess((getData(success($studienjahrObj)))); } + + public function getAllStudiensemesterAndAktOrNext() { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->StudiensemesterModel->addOrder("start", "DESC"); + $result = $this->StudiensemesterModel->getAktOrNextSemester(); + $aktuell = getData($result)[0]; + $this->StudiensemesterModel->addSelect('*'); + $result = $this->StudiensemesterModel->load(); + $studiensemester = getData($result); + + $this->terminateWithSuccess(array($studiensemester, $aktuell)); + } } diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index 17b360f8c..c787381f0 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -504,7 +504,7 @@ class Config extends FHCAPI_Controller { $result['combinePeople'] = [ 'title' => $this->p->t('stv', 'tab_combine_people'), - 'component' => './Stv/Studentenverwaltung/Details/CombinePeople.js', + 'component' => absoluteJsImportUrl('public/js/components/Stv/Studentenverwaltung/Details/CombinePeople.js'), 'config' => $config['combinePeople'] ]; } diff --git a/application/controllers/api/frontend/v1/stv/Dokumente.php b/application/controllers/api/frontend/v1/stv/Dokumente.php index 8a69d28ab..9f54d0aa4 100644 --- a/application/controllers/api/frontend/v1/stv/Dokumente.php +++ b/application/controllers/api/frontend/v1/stv/Dokumente.php @@ -596,8 +596,8 @@ class Dokumente extends FHCAPI_Controller buildDropdownEntryPrintArray("bescheid", "Bescheid (nur Voransicht)", "xml=abschlusspruefung.rdf.php&xsl_stg_kz=$studiengang_kz&xsl=Bescheid&output=pdf", $uid, 25, null), buildDropdownEntryPrintArray("diplomasupp", "Diploma Supplement (nur Voransicht)", "xml=diplomasupplement.xml.php&xsl_stg_kz=$studiengang_kz&xsl=DiplSupplement&output=pdf", $uid, 26, null), - buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf", $uid, 50, null), - buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf", $uid, 51, null), + buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf&ss=$studiensemester_kurzbz&xsl_stg_kz=$studiengang_kz", $uid, 50, null), + buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf&ss=$studiensemester_kurzbz&xsl_stg_kz=$studiengang_kz", $uid, 51, null), buildDropdownEntryPrintArray("zutrittskarte", "Zutrittskarte", "xsl=ZutrittskarteStud&output=pdf&data=$uid", $uid,200, "zutrittskarte.php"), buildDropdownEntryPrintArray("studienblatt", "Studienblatt", "xml=studienblatt.xml.php&xsl=Studienblatt&output=pdf&ss=$studiensemester_kurzbz", $uid, 60, null), buildDropdownEntryPrintArray("studienblatt_eng", "Studienblatt Englisch", "xml=studienblatt.xml.php&xsl=StudienblattEng&output=pdf&ss=$studiensemester_kurzbz", $uid, 61, null), @@ -686,8 +686,8 @@ class Dokumente extends FHCAPI_Controller buildDropdownEntryPrintArray("accountinfo", "Accountinfoblatt", "xml=accountinfoblatt.xml.php&xsl=AccountInfo&output=pdf", $uidString, 10, null), buildDropdownEntryPrintArray("ausbildungsvertrag", "Ausbildungsvertrag", "xml=ausbildungsvertrag.xml.php&xsl=Ausbildungsver&output=pdf", $uidString, 20, null), buildDropdownEntryPrintArray("ausbildungsvertrag_en", "Ausbildungsvertrag Englisch", "xml=ausbildungsvertrag.xml.php&xsl=AusbVerEng&output=pdf", $uidString, 21, null), - buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf", $uidString, 50, null), - buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf", $uidString, 51, null), + buildDropdownEntryPrintArray("studienbestaetigung", "Studienbestätigung", "xml=student.rdf.php&xsl=Inskription&output=pdf&ss=$studiensemester_kurzbz&xsl_stg_kz=$studiengang_kz", $uidString, 50, null), + buildDropdownEntryPrintArray("studienbestaetigung_en", "Studienbestätigung Englisch", "xml=student.rdf.php&xsl=InskriptionEng&output=pdf&ss=$studiensemester_kurzbz&xsl_stg_kz=$studiengang_kz", $uidString, 51, null), buildDropdownEntryPrintArray("zutrittskarte", "Zutrittskarte", "xsl=ZutrittskarteStud&output=pdf&data=$uidString", $uidString,200, "zutrittskarte.php"), buildDropdownEntryPrintArray("studienblatt", "Studienblatt", "xml=studienblatt.xml.php&xsl=Studienblatt&output=pdf&ss=$studiensemester_kurzbz", $uidString, 60, null), buildDropdownEntryPrintArray("studienblatt_eng", "Studienblatt Englisch", "xml=studienblatt.xml.php&xsl=StudienblattEng&output=pdf&ss=$studiensemester_kurzbz", $uidString, 61, null), diff --git a/application/controllers/api/frontend/v1/stv/Konto.php b/application/controllers/api/frontend/v1/stv/Konto.php index 384452f3e..ecd58671a 100644 --- a/application/controllers/api/frontend/v1/stv/Konto.php +++ b/application/controllers/api/frontend/v1/stv/Konto.php @@ -239,7 +239,7 @@ class Konto extends FHCAPI_Controller $data[$field] = $this->input->post($field); if (defined('FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE') && isset(unserialize(FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE)[$data['buchungstyp_kurzbz']])) { - $data['kostenstelle'] = unserialize(FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE)[$data['buchungstyp_kurzbz']]; + $data['studiengang_kz'] = unserialize(FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE)[$data['buchungstyp_kurzbz']]; } $result = []; diff --git a/application/controllers/api/frontend/v1/stv/Prestudent.php b/application/controllers/api/frontend/v1/stv/Prestudent.php index 7dc607d1a..d8c8d1ff2 100644 --- a/application/controllers/api/frontend/v1/stv/Prestudent.php +++ b/application/controllers/api/frontend/v1/stv/Prestudent.php @@ -43,7 +43,7 @@ class Prestudent extends FHCAPI_Controller // Load language phrases $this->loadPhrases([ - 'ui', 'studierendenantrag', 'lehre' + 'ui', 'studierendenantrag', 'lehre', 'global' ]); } @@ -98,11 +98,9 @@ class Prestudent extends FHCAPI_Controller 'person_id', 'berufstaetigkeit_code', 'ausbildungcode', - 'zgv_code', 'zgvort', 'zgvdatum', 'zgvnation', - 'zgvmas_code', 'zgvmaort', 'zgvmadatum', 'zgvmanation', @@ -110,7 +108,6 @@ class Prestudent extends FHCAPI_Controller 'bismelden', 'anmerkung', 'dual', - 'zgvdoktor_code', 'zgvdoktorort', 'zgvdoktordatum', 'zgvdoktornation', @@ -125,6 +122,57 @@ class Prestudent extends FHCAPI_Controller 'standort_code' ]; + // add zgv code fields only if user has permission + $this->load->library('PermissionLib'); + $prestudentres = $this->PrestudentModel->load($prestudent_id); + if(!hasData($prestudentres)) + { + $this->terminateWithError($this->p->t('ui', 'error_fieldNotFound', ['field' => 'Prestudent ' . $prestudent_id])); + } + $prestudent = (getData($prestudentres))[0]; + $bakkZgvStg = $this->permissionlib->getSTG_isEntitledFor('student/editBakkZgv') ?: array(); + $makkZgvStg = $this->permissionlib->getSTG_isEntitledFor('student/editMakkZgv') ?: array(); + $dokZgvStg = $this->permissionlib->getSTG_isEntitledFor('student/editDokZgv') ?: array(); + + if(in_array($prestudent->studiengang_kz, $bakkZgvStg)) + { + $array_allowed_props_prestudent[] = 'zgv_code'; + } + else if(!is_null($this->input->post('zgv_code'))) + { + $this->terminateWithError( + $this->p->t('global', 'zgv') + . ' - ' . + $this->p->t('ui', 'error_keineBerechtigungStg') + ); + } + + if(in_array($prestudent->studiengang_kz, $makkZgvStg)) + { + $array_allowed_props_prestudent[] = 'zgvmas_code'; + } + else if(!is_null($this->input->post('zgvmas_code'))) + { + $this->terminateWithError( + $this->p->t('lehre', 'zgvMaster') + . ' - ' . + $this->p->t('ui', 'error_keineBerechtigungStg') + ); + } + + if(in_array($prestudent->studiengang_kz, $dokZgvStg)) + { + $array_allowed_props_prestudent[] = 'zgvdoktor_code'; + } + else if(!is_null($this->input->post('zgvdoktor_code'))) + { + $this->terminateWithError( + $this->p->t('lehre', 'zgvDoktor') + . ' - ' . + $this->p->t('ui', 'error_keineBerechtigungStg') + ); + } + // add UDFs $result = $this->udflib->getDefinitionForModel($this->PrestudentModel); diff --git a/application/controllers/api/frontend/v1/stv/Status.php b/application/controllers/api/frontend/v1/stv/Status.php index 09a9f18b1..3c0a639cd 100644 --- a/application/controllers/api/frontend/v1/stv/Status.php +++ b/application/controllers/api/frontend/v1/stv/Status.php @@ -636,7 +636,7 @@ class Status extends FHCAPI_Controller $this->load->library('PrestudentLib'); - $this->prestudentlib->setFirstStudent( + $resFirstStudent = $this->prestudentlib->setFirstStudent( $prestudent_id, $lastAufgenommener->studiensemester_kurzbz, $lastAufgenommener->ausbildungssemester, @@ -645,9 +645,8 @@ class Status extends FHCAPI_Controller $this->input->post('statusgrund_id') ); - $this->getDataOrTerminateWithError($result); - - $this->db->trans_commit(); + $this->db->trans_complete(); + $this->getDataOrTerminateWithError($resFirstStudent); return $this->outputJsonSuccess(true); } diff --git a/application/controllers/api/frontend/v1/stv/Student.php b/application/controllers/api/frontend/v1/stv/Student.php index ad6883f94..943577bb3 100644 --- a/application/controllers/api/frontend/v1/stv/Student.php +++ b/application/controllers/api/frontend/v1/stv/Student.php @@ -321,6 +321,10 @@ class Student extends FHCAPI_Controller foreach ($array_allowed_props_benutzer as $prop) { $val = $this->input->post($prop); if ($val !== null) { + if($prop === 'alias' && $val === '') + { + $val = null; + } $update_benutzer[$prop] = $val; } } diff --git a/application/controllers/dashboard/Widget.php b/application/controllers/dashboard/Widget.php index 0da6fe8da..9966ddc12 100644 --- a/application/controllers/dashboard/Widget.php +++ b/application/controllers/dashboard/Widget.php @@ -33,19 +33,26 @@ class Widget extends Auth_Controller return $this->outputJsonSuccess([ "widget_id" => 0, "widget_kurzbz" => "notfound", - "arguments" => json_encode([ + "arguments" => [ "className" => 'alert-danger', "title" => 'Widget Not Found', "msg" => 'The widget with the id ' . $widget_id . ' could not be found' - ]), - "setup" => json_encode([ + ], + "setup" => [ "name" => 'Widget Not Found', - "file" => 'DashboardWidget/Default.js', + "file" => absoluteJsImportUrl('public/js/components/DashboardWidget/Default.js'), "width" => 1, "height" => 1 - ]) + ] ]); - return $this->outputJsonSuccess(current(getData($widget))); + + $widget = current(getData($widget)); + $widget->arguments = json_decode($widget->arguments); + $tmpsetup = json_decode($widget->setup); + $tmpsetup->file = absoluteJsImportUrl($tmpsetup->file); + $widget->setup = $tmpsetup; + + return $this->outputJsonSuccess($widget); } public function getAll() @@ -56,7 +63,16 @@ class Widget extends Auth_Controller if (isError($result)) return $this->outputJsonError(getError($result)); - $this->outputJsonSuccess(getData($result) ?: []); + $tmpwidgets = getData($result) ?: []; + $widgets = array_map(function($widget) { + $widget->arguments = json_decode($widget->arguments); + $tmpsetup = json_decode($widget->setup); + $tmpsetup->file = absoluteJsImportUrl($tmpsetup->file); + $widget->setup = $tmpsetup; + return $widget; + }, $tmpwidgets); + + $this->outputJsonSuccess($widgets); } public function getWidgetsForDashboard() @@ -71,7 +87,16 @@ class Widget extends Auth_Controller ]); } - $this->outputJsonSuccess(getData($result) ?: []); + $tmpwidgets = getData($result) ?: []; + $widgets = array_map(function($widget) { + $widget->arguments = json_decode($widget->arguments); + $tmpsetup = json_decode($widget->setup); + $tmpsetup->file = absoluteJsImportUrl($tmpsetup->file); + $widget->setup = $tmpsetup; + return $widget; + }, $tmpwidgets); + + $this->outputJsonSuccess($widgets); } public function setAllowed() diff --git a/application/controllers/jobs/AbgabetoolJob.php b/application/controllers/jobs/AbgabetoolJob.php new file mode 100644 index 000000000..51b2b4920 --- /dev/null +++ b/application/controllers/jobs/AbgabetoolJob.php @@ -0,0 +1,621 @@ +_ci =& get_instance(); + + $this->_ci->load->helper('hlp_sancho_helper'); + + $this->_ci->load->model('education/Projektarbeit_model', 'ProjektarbeitModel'); + $this->_ci->load->model('education/Projektbetreuer_model', 'ProjektbetreuerModel'); + $this->_ci->load->model('education/Paabgabe_model', 'PaabgabeModel'); + $this->_ci->load->model('crm/Student_model', 'StudentModel'); + $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel'); + $this->_ci->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel'); + + $this->_ci->load->config('abgabe'); + $this->loadPhrases([ + 'abgabetool' + ]); + } + + public function notifyAssistenzAboutChangedAbgaben() { + + $this->_ci->logInfo('Start job FHC-Core->notifyAssistenzAboutChangedAbgaben'); + + $interval = $this->_ci->config->item('PAABGABE_EMAIL_JOB_INTERVAL'); + $relevantTypes = $this->_ci->config->item('RELEVANT_PAABGABETYPEN_SAMMELMAIL_ASSISTENZ'); + // get all new or changed termine in interval + $result = $this->_ci->PaabgabeModel->findAbgabenNewOrUpdatedSince($interval, $relevantTypes); + + $retval = getData($result); + + if(count($retval) == 0) { + $this->_ci->logInfo("Keine Emails an Assistenzen über neue oder veränderte Termine versandt"); + return; + } + + // group changed/new abgaben for projektarbeiten + $projektarbeiten = []; + foreach($retval as $newOrChangedAbgabe) { + // Check if the current item has a 'projektarbeit_id' field. + // Replace 'projektarbeit_id' with the actual key name if it's different. + if (isset($newOrChangedAbgabe->projektarbeit_id)) { + $projektarbeitId = $newOrChangedAbgabe->projektarbeit_id; + + // If the 'projektarbeit_id' is not yet a key in $projektarbeiten, + // initialize it as an empty array. + if (!isset($projektarbeiten[$projektarbeitId])) { + $projektarbeiten[$projektarbeitId] = []; + } + + // Add the current row to the array associated with its 'projektarbeit_id'. + $projektarbeiten[$projektarbeitId][] = $newOrChangedAbgabe; + } + } + + // for each projektarbeit fetch their assistenz and same them in their own dictionary to avoid too many mails + $assistenzMap = []; + // for each projektarbeit fetch their betreuer and save them in their own dictionary to avoid too many mails + $projektarbeitBetreuerMap = []; + forEach($projektarbeiten as $projektarbeit_id => $abgaben) { + + $assistenzResult = $this->_ci->OrganisationseinheitModel->getAssistenzForOE($abgaben[0]->stg_oe_kurzbz); + + forEach($assistenzResult->retval as $assistenzRow) { + if (!isset($assistenzMap[$assistenzRow->person_id])) { + $assistenzMap[$assistenzRow->person_id] = []; + } + + // Add the current $assistenzRow to the $assistenzMap as an array associated with its projektarbeit_id. + $assistenzMap[$assistenzRow->person_id][] = [$projektarbeit_id, $assistenzRow]; + } + + $betreuerResult = $this->_ci->ProjektbetreuerModel->getAllBetreuerOfProjektarbeit($projektarbeit_id); + + forEach($betreuerResult->retval as $betreuerRow) { + if (!isset($projektarbeitBetreuerMap[$projektarbeit_id])) { + $projektarbeitBetreuerMap[$projektarbeit_id] = []; + } + + // Add the current betreuerRow to the betreuerMap as an array associated with its projektarbeit_id. + $projektarbeitBetreuerMap[$projektarbeit_id][] = $betreuerRow; + } + } + + $count = 0; + foreach($assistenzMap as $assistenz_person_id => $tupelArr) { + + $abgabenString = '
'; + + foreach($tupelArr as $tupel) { + $projektarbeit_id = $tupel[0]; + $assistenzRow = $tupel[1]; + + $betreuerArray = $projektarbeitBetreuerMap[$projektarbeit_id] ?? []; + $changedAbgaben = $projektarbeiten[$projektarbeit_id]; + + $relevantAbgaben = array_values(array_filter($changedAbgaben, function($abgabetermin) use ($assistenzRow) { + if($abgabetermin->updatevon == null && $abgabetermin->insertvon != $assistenzRow->uid) { + return $abgabetermin; + } else if($abgabetermin->updatevon != null && $abgabetermin->updatevon != $assistenzRow->uid) { + return $abgabetermin; + } + })); + + if(count($relevantAbgaben) == 0) { + continue; + } + + // Format the Student Name + $s = $relevantAbgaben[0]; + $nameParts = []; + if (!empty($s->titelpre)) $nameParts[] = $s->titelpre; + $nameParts[] = $s->vorname; + $nameParts[] = $s->nachname; + if (!empty($s->titelpost)) $nameParts[] = $s->titelpost; + $studentFullName = implode(' ', $nameParts); + + // Format the Supervisors string + $betreuerStrings = []; + foreach($betreuerArray as $b) { + $bNameParts = []; + if (!empty($b->titelpre)) $bNameParts[] = $b->titelpre; + $bNameParts[] = $b->vorname; + $bNameParts[] = $b->nachname; + if (!empty($b->titelpost)) $bNameParts[] = $b->titelpost; + + $bFullName = implode(' ', $bNameParts); + $betreuerStrings[] = "{$bFullName} ({$b->betreuerart_kurzbz})"; + } + $allBetreuerFormatted = implode(', ', $betreuerStrings); + + $projektarbeit_titel = $s->titel ?? 'Kein Titel vergeben'; + + // Project Header Section + $abgabenString .= " +
+ Projekt: {$projektarbeit_titel}
+
+ Studierende/r: {$studentFullName} +
+
+ Betreuer: {$allBetreuerFormatted} +
+ + ID: {$projektarbeit_id} | Stg: {$s->stgtyp}{$s->stgkz} ({$s->studiensemester_kurzbz}) + +
"; + + // Start Table + $abgabenString .= ' + + + + + + + + '; + + foreach ($relevantAbgaben as $abgabe) { + $dateEmailFormatted = (new DateTime($abgabe->datum))->format('d.m.Y'); + $abgabedatumFormatted = (new DateTime($abgabe->abgabedatum))->format('d.m.Y'); + $kurzbzLine = !empty($abgabe->kurzbz) ? "
{$abgabe->kurzbz}" : ""; + + $abgabenString .= " + + + + "; + } + + $abgabenString .= '
ZieldatumBezeichnung
{$dateEmailFormatted} + {$abgabe->bezeichnung}{$kurzbzLine} +
'; + } + + $abgabenString .= '
'; + + // done with building the change list, now send it + $assistenzRow = $tupelArr[0][1]; + $anrede = $assistenzRow->anrede; + $anredeFillString = $assistenzRow->anrede == "Herr" ? "r" : ""; + $fullFormattedNameString = $assistenzRow->first; + + + + $path = $this->_ci->config->item('URL_ASSISTENZ'); + $url = CIS_ROOT.$path; + + $body_fields = array( + 'anrede' => $anrede, + 'anredeFillString' => $anredeFillString, + 'fullFormattedNameString' => $fullFormattedNameString, + 'abgabenString' => $abgabenString, + 'linkAbgabetool' => $url + ); + + $email = $assistenzRow->uid."@".DOMAIN; + + // send email with bundled info + sendSanchoMail( + 'PAAChangesAssSM', + $body_fields, + $email, + $this->p->t('abgabetool', 'changedAbgabeterminev2') + ); + + $count++; + } + + $this->_ci->logInfo($count . " Emails erfolgreich versandt"); + $this->_ci->logInfo('End job FHC-Core->notifyAssistenzAboutChangedAbgaben'); + } + + public function notifyBetreuerAboutChangedAbgaben() { + + $this->_ci->logInfo('Start job FHC-Core->notifyBetreuerAboutChangedAbgaben'); + + $interval = $this->_ci->config->item('PAABGABE_EMAIL_JOB_INTERVAL'); + + $relevantTypes = $this->_ci->config->item('RELEVANT_PAABGABETYPEN_SAMMELMAIL_BETREUER'); + + // get all new or changed termine in interval + $result = $this->_ci->PaabgabeModel->findAbgabenNewOrUpdatedSince($interval, $relevantTypes); + $retval = getData($result); + + if(count($retval) == 0) { + $this->_ci->logInfo("Keine Emails an Betreuer über neue oder veränderte Termine versandt"); + return; + } + + // group changed/new abgaben for projektarbeiten + $projektarbeiten = []; + foreach($retval as $newOrChangedAbgabe) { + // Check if the current item has a 'projektarbeit_id' field. + // Replace 'projektarbeit_id' with the actual key name if it's different. + if (isset($newOrChangedAbgabe->projektarbeit_id)) { + $projektarbeitId = $newOrChangedAbgabe->projektarbeit_id; + + // If the 'projektarbeit_id' is not yet a key in $projektarbeiten, + // initialize it as an empty array. + if (!isset($projektarbeiten[$projektarbeitId])) { + $projektarbeiten[$projektarbeitId] = []; + } + + // Add the current row to the array associated with its 'projektarbeit_id'. + $projektarbeiten[$projektarbeitId][] = $newOrChangedAbgabe; + } + } + + // for each projektarbeit fetch their betreuer and save them in their own dictionary to avoid too many mails + $betreuerMap = []; + forEach($projektarbeiten as $projektarbeit_id => $abgaben) { + $betreuerResult = $this->_ci->ProjektbetreuerModel->getAllBetreuerOfProjektarbeit($projektarbeit_id); + + forEach($betreuerResult->retval as $betreuerRow) { + if (!isset($betreuerMap[$betreuerRow->person_id])) { + $betreuerMap[$betreuerRow->person_id] = []; + } + + // Add the current betreuerRow to the betreuerMap as an array associated with its projektarbeit_id. + $betreuerMap[$betreuerRow->person_id][] = [$projektarbeit_id, $betreuerRow]; + } + } + + $count = 0; + // now iterate over the betreuerMap and build 1 email about all projektarbeiten and their new/changed termine + // $tupel = [$projektarbeit_id, $betreuerRow], each betreuer has 0..n [projektarbeit_id, changedAbgaben] tupel + forEach($betreuerMap as $betreuer_person_id => $tupelArr) { + + // start the container + $abgabenString = '
'; + + $result = $this->_ci->ProjektarbeitModel->getProjektbetreuerAnrede($betreuer_person_id); + $data = getData($result)[0]; + + $anrede = $data->anrede; + $anredeFillString = $data->anrede == "Herr" ? "r" : ""; + $fullFormattedNameString = $data->first; + + forEach($tupelArr as $tupel) { + $projektarbeit_id = $tupel[0]; + $betreuerRow = $tupel[1]; + + $changedAbgaben = $projektarbeiten[$projektarbeit_id]; + + $relevantAbgaben = array_values(array_filter($changedAbgaben, function($abgabetermin) use ($betreuerRow) { + if($abgabetermin->updatevon == null && $abgabetermin->insertvon != $betreuerRow->uid) { + return $abgabetermin; + } else if($abgabetermin->updatevon != null && $abgabetermin->updatevon != $betreuerRow->uid) { + return $abgabetermin; + } + })); + + if(count($relevantAbgaben) == 0) { + continue; + } + + // format the Student Name + $s = $relevantAbgaben[0]; + $nameParts = []; + if (!empty($s->titelpre)) $nameParts[] = $s->titelpre; + $nameParts[] = $s->vorname; + $nameParts[] = $s->nachname; + if (!empty($s->titelpost)) $nameParts[] = $s->titelpost; + $studentFullName = implode(' ', $nameParts); + + $projektarbeit_titel = $s->titel ?? 'Kein Titel vergeben'; + + // project header section + $abgabenString .= " +
+ Projekt: {$projektarbeit_titel}
+
+ Studierende/r: {$studentFullName} +
+ + ID: {$projektarbeit_id} | Rolle: {$betreuerRow->betreuerart_kurzbz} | + Stg: {$s->stgtyp}{$s->stgkz} ({$s->studiensemester_kurzbz}) + +
"; + + // start table + $abgabenString .= ' + + + + + + + + '; + + foreach ($relevantAbgaben as $abgabe) { + $dateEmailFormatted = (new DateTime($abgabe->datum))->format('d.m.Y'); + $abgabedatumFormatted = (new DateTime($abgabe->abgabedatum))->format('d.m.Y'); + $kurzbzLine = !empty($abgabe->kurzbz) ? "
{$abgabe->kurzbz}" : ""; + + $abgabenString .= " + + + + "; + } + + $abgabenString .= '
ZieldatumBezeichnung
{$dateEmailFormatted} + {$abgabe->bezeichnung}{$kurzbzLine} +
'; + } + + // close container + $abgabenString .= '
'; + + // done with building the change list, now send it + $betreuerRow = $tupelArr[0][1]; + + $path = $this->_ci->config->item('URL_MITARBEITER'); + $url = CIS_ROOT.$path; + + $body_fields = array( + 'anrede' => $anrede, + 'anredeFillString' => $anredeFillString, + 'fullFormattedNameString' => $fullFormattedNameString, + 'abgabenString' => $abgabenString, + 'linkAbgabetool' => $url + ); + + $email = $betreuerRow->uid ? $betreuerRow->uid."@".DOMAIN : $betreuerRow->private_email; + + // send email with bundled info + sendSanchoMail( + 'PAAChangesBetSM', + $body_fields, + $email, + $this->p->t('abgabetool', 'changedAbgabeterminev2') + ); + + $count++; + } + + $this->_ci->logInfo($count . " Emails erfolgreich versandt"); + $this->_ci->logInfo('End job FHC-Core->notifyBetreuerAboutChangedAbgaben'); + } + + public function notifyBetreuerMail() { + // send all new projektarbeit abgabe UPLOADS since the last job run to the related betreuer + // this job gathers all new or changed file uploads via field 'abgabedatum', enduploads still + // send an email directly after happening since they are kind of important + + $this->_ci->logInfo('Start job FHC-Core->notifyBetreuerMail'); + + // dont filter for relevant types since this mail should gather all UPLOAD info + + $interval = $this->_ci->config->item('PAABGABE_EMAIL_JOB_INTERVAL'); + + $result = $this->_ci->PaabgabeModel->findAbgabenNewOrUpdatedSinceByAbgabedatum($interval); + $retval = getData($result); + + // retval are paabgaben joined with projektarbeit and betreuer + if(count($retval) == 0) { + $this->logInfo("Keine Emails über neue Paabgaben an Betreuer versandt"); + return; + } + + // group contents per betreuer person_id + $betreuer_uids = []; + forEach($retval as $paabgabe) { + if(!isset($betreuer_uids[$paabgabe->person_id])) { + $betreuer_uids[$paabgabe->person_id] = []; + } + + $betreuer_uids[$paabgabe->person_id][] = $paabgabe; + } + + $count = 0; + forEach ($betreuer_uids as $person_id => $abgaben) { + // $person_id is from betreuer + + $result = $this->_ci->ProjektarbeitModel->getProjektbetreuerAnrede($person_id); + $data = getData($result)[0]; + + $anrede = $data->anrede; + $anredeFillString = $data->anrede == "Herr" ? "r" : ""; + $fullFormattedNameString = $data->first; + + // sorting $abgaben array by datum + usort($abgaben, function ($a, $b) { + return strtotime($a->datum) <=> strtotime($b->datum); + }); + + $projektarbeit_titel = $abgaben[0]->titel; + + // initialize the table and headers + $abgabenString = ' + + + + + + + + + + '; + + foreach ($abgaben as $abgabe) { + // format the student name + $nameParts = []; + if (!empty($abgabe->titelpre)) $nameParts[] = $abgabe->titelpre; + $nameParts[] = $abgabe->vorname; + $nameParts[] = $abgabe->nachname; + if (!empty($abgabe->titelpost)) $nameParts[] = $abgabe->titelpost; + $studentFullName = implode(' ', $nameParts); + + // format dates inline + $dateEmailFormatted = (new DateTime($abgabe->datum))->format('d.m.Y'); + $abgabedatumFormatted = (new DateTime($abgabe->abgabedatum))->format('d.m.Y'); + + // handle the optional Kurzbezeichnung + $kurzbzLine = !empty($abgabe->kurzbz) ? "
{$abgabe->kurzbz}" : ""; + + $abgabenString .= " + + + + + + "; + } + + $abgabenString .= '
ZieldatumStudierende/rBezeichnungAbgabedatum
{$dateEmailFormatted}{$studentFullName} + {$abgabe->bezeichnung}{$kurzbzLine} + {$abgabedatumFormatted}
'; + + $path = $this->_ci->config->item('URL_MITARBEITER'); + $url = CIS_ROOT.$path; + + $body_fields = array( + 'anrede' => $anrede, + 'anredeFillString' => $anredeFillString, + 'fullFormattedNameString' => $fullFormattedNameString, + 'paTitel' => $projektarbeit_titel, + 'abgabenString' => $abgabenString, + 'linkAbgabetool' => $url + ); + + $result = $this->_ci->ProjektbetreuerModel->getBetreuerOfProjektarbeit($abgaben[0]->projektarbeit_id, $abgaben[0]->betreuerart_kurzbz); + $data = getData($result)[0]; + + $email = $data->uid ? $data->uid."@".DOMAIN : $data->private_email; + + // send email with bundled info + sendSanchoMail( + 'PaabgabeUpdatesBetSM', + $body_fields, + $email, + $this->p->t('abgabetool', 'changedAbgabeterminev2') + ); + + $count++; + } + + $this->_ci->logInfo($count . " Emails erfolgreich versandt"); + $this->_ci->logInfo('End job FHC-Core->notifyBetreuerMail'); + } + + public function notifyStudentMail() + { + // send all new projektarbeit abgabe since the last job run to the related student + + $this->_ci->logInfo('Start job FHC-Core->notifyStudentMail'); + + $interval = $this->_ci->config->item('PAABGABE_EMAIL_JOB_INTERVAL'); + + $relevantTypes = $this->_ci->config->item('RELEVANT_PAABGABETYPEN_SAMMELMAIL_STUDENT'); + + $result = $this->_ci->PaabgabeModel->findAbgabenNewOrUpdatedSince($interval, $relevantTypes); + $retval = getData($result); + + if(count($retval) == 0) { + $this->_ci->logInfo("Keine Emails an Studenten versandt"); + return; + } + + // group results per projektarbeit/student_uid + $student_uids = []; + forEach($retval as $paabgabe) { + if(!isset($student_uids[$paabgabe->student_uid])) { + $student_uids[$paabgabe->student_uid] = []; + } + + $student_uids[$paabgabe->student_uid][] = $paabgabe; + } + + $count = 0; + foreach ($student_uids as $uid => $abgaben) { + // $uid is the student's UID + $result = $this->_ci->StudentModel->getEmailAnredeForStudentUID($uid); + $data = getData($result)[0]; + + // $abgabe is the array of paabgabe objects + $anredeFillString = $data->anrede=="Herr"?"r":""; + $fullFormattedNameString = trim($data->titelpre." ".$data->vorname." ".$data->vornamen." ".$data->nachname." ".$data->titelpost); + + // https://www.php.net/manual/en/migration70.new-features.php#migration70.new-features.spaceship-op + // php has spaceships 🚀🚀🚀🚀🚀 + usort($abgaben, function($a, $b) { + return strtotime($a->datum) <=> strtotime($b->datum); + }); + + $projektarbeit_titel = $abgaben[0]->titel; + + // initialize the table and headers + $abgabenString = ' + + + + + + + + '; + + foreach ($abgaben as $abgabe) { + $dateEmailFormatted = (new DateTime($abgabe->datum))->format('d.m.Y'); + + // handle the optional Kurzbezeichnung + $kurzbzLine = !empty($abgabe->kurzbz) ? "
{$abgabe->kurzbz}" : ""; + + $abgabenString .= " + + + + "; + } + + $abgabenString .= '
ZieldatumBezeichnung / Hinweis
+ {$dateEmailFormatted} + + {$abgabe->bezeichnung}{$kurzbzLine} +
'; + + $route = $this->_ci->config->item('URL_STUDENTS'); + $url = CIS_ROOT.$route; + + $body_fields = array( + 'anrede' => $data->anrede, + 'anredeFillString' => $anredeFillString, + 'fullFormattedNameString' => $fullFormattedNameString, + 'paTitel' => $projektarbeit_titel, + 'abgabenString' => $abgabenString, + 'linkAbgabetool' => $url + ); + + // send email with bundled info + sendSanchoMail( + 'PaabgabeUpdatesSammelmail', + $body_fields, + $uid.'@'.DOMAIN, + $this->p->t('abgabetool', 'changedAbgabeterminev2') + ); + + $count++; + + } + + $this->_ci->logInfo($count . " Emails erfolgreich versandt"); + $this->_ci->logInfo('End job FHC-Core->notifyStudentMail'); + } +} \ No newline at end of file diff --git a/application/core/FHCAPI_Controller.php b/application/core/FHCAPI_Controller.php index dad56334d..e81506d4b 100644 --- a/application/core/FHCAPI_Controller.php +++ b/application/core/FHCAPI_Controller.php @@ -266,7 +266,7 @@ class FHCAPI_Controller extends Auth_Controller } // --------------------------------------------------------------- - // Security + // Security Begin // --------------------------------------------------------------- /** @@ -287,4 +287,31 @@ class FHCAPI_Controller extends Auth_Controller 'required_permissions' => $this->_rpsToString($requiredPermissions, $this->router->method) ], self::ERROR_TYPE_AUTH); } + + // --------------------------------------------------------------- + // Security End + // --------------------------------------------------------------- + + /** + * Checks the client's total request size (Content-Length) against the minimum + * effective PHP limit (min of upload_max_filesize, post_max_size, memory_limit). + * This preempts failures that result in vague "missing parameters" errors on large files. + * + * @return void + */ + protected function checkUploadSize() { + // this number represents bytes + $content_length_bytes = (int)$this->input->server('CONTENT_LENGTH'); + $content_length = $content_length_bytes / 1000000; + + //get max serverside size upload -> this comes in megabytes + $max_upload = (int)(ini_get('upload_max_filesize')); + $max_post = (int)(ini_get('post_max_size')); + $memory_limit = (int)(ini_get('memory_limit')); + $max_upload_mb = min($max_upload, $max_post, $memory_limit); // smallest of 3 config values + + if($content_length >= $max_upload_mb) { + $this->terminateWithError($this->p->t('global', 'filesizeExceeded'), 'general'); + } + } } diff --git a/application/helpers/hlp_header_helper.php b/application/helpers/hlp_header_helper.php index dfdde6f27..c8b70d722 100644 --- a/application/helpers/hlp_header_helper.php +++ b/application/helpers/hlp_header_helper.php @@ -185,7 +185,15 @@ function generateJSModulesInclude($JSModules) for ($tmpJSsCounter = 0; $tmpJSsCounter < count($tmpJSs); $tmpJSsCounter++) { - $toPrint = sprintf($jsInclude, base_url($tmpJSs[$tmpJSsCounter].$cachetoken)).PHP_EOL; + if($ci->config->item('use_fhcomplete_build_version_in_path')) + { + $relurl = preg_replace('#public/#', 'public/' . $ci->config->item('fhcomplete_build_version') . '/', $tmpJSs[$tmpJSsCounter]); + $toPrint = sprintf($jsInclude, base_url($relurl)).PHP_EOL; + } + else + { + $toPrint = sprintf($jsInclude, base_url($tmpJSs[$tmpJSsCounter].$cachetoken)).PHP_EOL; + } if ($tmpJSsCounter > 0) $toPrint = "\t\t".$toPrint; @@ -253,7 +261,15 @@ function generateSkipLink($skipID) function absoluteJsImportUrl($relurl) { $ci =& get_instance(); - $url = base_url($relurl) . '?'. $ci->config->item('fhcomplete_build_version'); + $ci->load->config('javascript'); + if($ci->config->item('use_fhcomplete_build_version_in_path')) + { + $url = base_url(preg_replace('#^public/#', 'public/' . $ci->config->item('fhcomplete_build_version') . '/', $relurl)); + } + else + { + $url = base_url($relurl) . '?'. $ci->config->item('fhcomplete_build_version'); + } return $url; } diff --git a/application/libraries/PrestudentLib.php b/application/libraries/PrestudentLib.php index a57533da0..b1f2dc900 100644 --- a/application/libraries/PrestudentLib.php +++ b/application/libraries/PrestudentLib.php @@ -723,7 +723,7 @@ class PrestudentLib // Generate Alias - $alias = ''; + $alias = null; if (!defined('GENERATE_ALIAS_STUDENT') || GENERATE_ALIAS_STUDENT === true ) { diff --git a/application/models/crm/Student_model.php b/application/models/crm/Student_model.php index ca9cfe4c3..ab073996f 100644 --- a/application/models/crm/Student_model.php +++ b/application/models/crm/Student_model.php @@ -279,4 +279,12 @@ class Student_model extends DB_Model { return $student_uid . '@' . DOMAIN; } + + public function getEmailAnredeForStudentUID($student_uid) { + $qry = "SELECT anrede, titelpre, vorname, vornamen, nachname, titelpost + FROM campus.vw_student + WHERE uid = ?"; + + return $this->execReadOnlyQuery($qry, array($student_uid)); + } } diff --git a/application/models/education/Lehrveranstaltung_model.php b/application/models/education/Lehrveranstaltung_model.php index 7347cf2ca..ccac33bc7 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) @@ -386,6 +386,37 @@ class Lehrveranstaltung_model extends DB_Model return $this->execQuery($query, array($lehrveranstaltung_id, $studiensemester_kurzbz)); } + + /** + * Get LV-Leitung of given Lehrveranstaltung ID and Studiensemester. + * + * @param $lehrveranstaltung_id + * @param $studiensemester + * @return array|stdClass|null + */ + public function getLvLeitung($lehrveranstaltung_id, $studiensemester) + { + $params = [$lehrveranstaltung_id, $studiensemester]; + + $qry = " + SELECT + vorname, nachname, mitarbeiter_uid, lehrfunktion_kurzbz + FROM + lehre.tbl_lehreinheit + JOIN lehre.tbl_lehreinheitmitarbeiter lema USING (lehreinheit_id) + JOIN public.tbl_benutzer b ON b.uid = lema.mitarbeiter_uid + JOIN public.tbl_person p using (person_id) + WHERE + tbl_lehreinheit.lehrveranstaltung_id= ? + AND tbl_lehreinheit.studiensemester_kurzbz = ? + AND lehrfunktion_kurzbz = 'LV-Leitung' + ORDER BY + lema.insertamum DESC + LIMIT 1 + "; + + return $this->execQuery($qry, $params); + } /** * Gets all Leiter of Lehrveranstaltungsorganisationseinheit * @param $lehrveranstaltung_id 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/Paabgabe_model.php b/application/models/education/Paabgabe_model.php index 343a86706..aa61bbaae 100644 --- a/application/models/education/Paabgabe_model.php +++ b/application/models/education/Paabgabe_model.php @@ -60,5 +60,52 @@ class Paabgabe_model extends DB_Model return $this->execReadOnlyQuery($qry, array($person_id)); } - + + public function findAbgabenNewOrUpdatedSince($interval, $relevantTypes) + { + + $query = "SELECT projektarbeit_id, paabgabe_id, paabgabetyp_kurzbz, fixtermin, datum, campus.tbl_paabgabe.kurzbz, campus.tbl_paabgabetyp.bezeichnung, campus.tbl_paabgabe.abgabedatum, + campus.tbl_paabgabe.insertvon, campus.tbl_paabgabe.insertamum, campus.tbl_paabgabe.updatevon, campus.tbl_paabgabe.updateamum, + campus.tbl_paabgabe.note, upload_allowed, beurteilungsnotiz, student_uid, tbl_projektarbeit.note, lehre.tbl_projektarbeit.titel, + UPPER(tbl_studiengang.typ) as stgtyp, UPPER(tbl_studiengang.kurzbz) as stgkz, public.tbl_studiengang.studiengang_kz, + public.tbl_studiengang.oe_kurzbz as stg_oe_kurzbz, tbl_lehreinheit.studiensemester_kurzbz, + public.tbl_person.anrede, public.tbl_person.titelpre, public.tbl_person.vorname, public.tbl_person.nachname, public.tbl_person.titelpost + FROM campus.tbl_paabgabe + JOIN campus.tbl_paabgabetyp USING (paabgabetyp_kurzbz) + JOIN lehre.tbl_projektarbeit USING (projektarbeit_id) + JOIN lehre.tbl_lehreinheit using(lehreinheit_id) + JOIN lehre.tbl_lehrveranstaltung using(lehrveranstaltung_id) + JOIN public.tbl_studiengang on(lehre.tbl_lehrveranstaltung.studiengang_kz = public.tbl_studiengang.studiengang_kz) + JOIN public.tbl_benutzer ON (public.tbl_benutzer.uid = student_uid) + JOIN public.tbl_person USING (person_id) + + WHERE (campus.tbl_paabgabe.insertamum >= NOW() - INTERVAL ? + OR campus.tbl_paabgabe.updateamum >= NOW() - INTERVAL ?) + AND campus.tbl_paabgabe.paabgabetyp_kurzbz IN ?"; + + return $this->execQuery($query, [$interval, $interval, $relevantTypes]); + } + + public function findAbgabenNewOrUpdatedSinceByAbgabedatum($interval) { + + $query = "SELECT projektarbeit_id, paabgabe_id, paabgabetyp_kurzbz, fixtermin, datum, kurzbz, campus.tbl_paabgabetyp.bezeichnung, campus.tbl_paabgabe.abgabedatum, + campus.tbl_paabgabe.insertvon, campus.tbl_paabgabe.insertamum, campus.tbl_paabgabe.updatevon, campus.tbl_paabgabe.updateamum, + campus.tbl_paabgabe.note, upload_allowed, beurteilungsnotiz, student_uid, tbl_projektarbeit.note, lehre.tbl_projektarbeit.titel, + lehre.tbl_projektbetreuer.betreuerart_kurzbz, lehre.tbl_projektbetreuer.person_id, + public.tbl_person.anrede, public.tbl_person.titelpre, public.tbl_person.vorname, public.tbl_person.nachname, public.tbl_person.titelpost + + FROM campus.tbl_paabgabe + JOIN campus.tbl_paabgabetyp USING (paabgabetyp_kurzbz) + JOIN lehre.tbl_projektarbeit USING (projektarbeit_id) + JOIN lehre.tbl_projektbetreuer USING (projektarbeit_id) + JOIN public.tbl_benutzer ON (public.tbl_benutzer.uid = student_uid) + JOIN public.tbl_person ON (public.tbl_benutzer.person_id = public.tbl_person.person_id) + + WHERE campus.tbl_paabgabe.abgabedatum IS NOT NULL + AND campus.tbl_paabgabe.abgabedatum >= NOW() - INTERVAL ? + ORDER BY abgabedatum DESC + "; + + return $this->execQuery($query, [$interval]); + } } diff --git a/application/models/education/Paabgabetyp_model.php b/application/models/education/Paabgabetyp_model.php index b672a3f0e..034daca44 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 ORDER BY bezeichnung"; + + return $this->execReadOnlyQuery($qry); + } } diff --git a/application/models/education/Projektarbeit_model.php b/application/models/education/Projektarbeit_model.php index 414d1d1be..d80878f6d 100644 --- a/application/models/education/Projektarbeit_model.php +++ b/application/models/education/Projektarbeit_model.php @@ -64,16 +64,16 @@ class Projektarbeit_model extends DB_Model if (isset($projekttyp)) { if (is_array($projekttyp)) - $qry .= ' AND tbl_projektarbeit.projekttyp_kurzbz IN ?'; + $qry .= ' AND pa.projekttyp_kurzbz IN ?'; else - $qry .= ' AND tbl_projektarbeit.projekttyp_kurzbz=?'; + $qry .= ' AND pa.projekttyp_kurzbz=?'; $params[] = $projekttyp; } if (isset($final)) { - $qry .= ' AND tbl_projektarbeit.final=?'; + $qry .= ' AND pa.final=?'; $params[] = $final; } @@ -109,36 +109,36 @@ class Projektarbeit_model extends DB_Model */ public function getStudentProjektarbeitenWithBetreuer($studentUID) { - $betreuerQuery = " - SELECT + $betreuerQuery = "SELECT * FROM (SELECT DISTINCT ON(projektarbeit_id) vorname as bvorname, nachname as bnachname, titelpre as btitelpre, titelpost AS btitelpost, - titelpost AS btitelpost, tbl_betreuerart.beschreibung AS betreuerart_beschreibung, - (SELECT person_id - FROM lehre.tbl_projektbetreuer + (SELECT person_id + FROM lehre.tbl_projektbetreuer WHERE projektarbeit_id=tbl_projektarbeit.projektarbeit_id - AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter') LIMIT 1) AS zweitbetreuer_person_id, - (SELECT betreuerart_kurzbz - FROM lehre.tbl_projektbetreuer + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter') LIMIT 1) AS zweitbetreuer_person_id, + (SELECT betreuerart_kurzbz + FROM lehre.tbl_projektbetreuer WHERE projektarbeit_id=tbl_projektarbeit.projektarbeit_id - AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter') LIMIT 1) AS zweitbetreuer_betreuerart_kurzbz, - (SELECT tbl_betreuerart.beschreibung - FROM lehre.tbl_projektbetreuer JOIN lehre.tbl_betreuerart USING(betreuerart_kurzbz) + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter') LIMIT 1) AS zweitbetreuer_betreuerart_kurzbz, + (SELECT tbl_betreuerart.beschreibung + FROM lehre.tbl_projektbetreuer JOIN lehre.tbl_betreuerart USING(betreuerart_kurzbz) WHERE projektarbeit_id=tbl_projektarbeit.projektarbeit_id - AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter', 'Senatsmitglied') LIMIT 1) AS zweitbetreuer_betreuerart_beschreibung, - + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter', 'Senatsmitglied') LIMIT 1) AS zweitbetreuer_betreuerart_beschreibung, + tbl_betreuerart.betreuerart_kurzbz, person_id as bperson_id, projektarbeit_id, lehre.tbl_projekttyp.bezeichnung as projekttypbezeichnung, + lehre.tbl_projekttyp.projekttyp_kurzbz as projekttypkurzbz, lehre.tbl_lehreinheit.studiensemester_kurzbz, lehre.tbl_lehrveranstaltung.studiengang_kz, public.tbl_studiengang.kurzbzlang, - lehre.tbl_projektbetreuer.note as note, + lehre.tbl_projektarbeit.note as note, + lehre.tbl_note.bezeichnung as note_bezeichnung, public.tbl_mitarbeiter.mitarbeiter_uid, lehre.tbl_projektarbeit.titel as titel, lehre.tbl_projektarbeit.sprache as sprache, @@ -147,9 +147,8 @@ class Projektarbeit_model extends DB_Model lehre.tbl_projektarbeit.schlagwoerter as schlagwoerter, lehre.tbl_projektarbeit.schlagwoerter_en as schlagwoerter_en, lehre.tbl_projektarbeit.abstract as abstract, - lehre.tbl_projektarbeit.abstract_en as abstract_en, - (SELECT abgeschicktvon FROM extension.tbl_projektarbeitsbeurteilung WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id AND betreuer_person_id = tbl_projektbetreuer.person_id) AS babgeschickt, - (SELECT abgeschicktvon FROM extension.tbl_projektarbeitsbeurteilung WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter') LIMIT 1) AS zweitbetreuer_abgeschickt, + lehre.tbl_projektarbeit.abstract_en as abstract_en, + lehre.tbl_projektarbeit.insertamum as insertamum, (SELECT datum FROM campus.tbl_paabgabe WHERE paabgabetyp_kurzbz = 'end' AND abgabedatum IS NOT NULL AND projektarbeit_id = tbl_projektarbeit.projektarbeit_id LIMIT 1) AS abgegeben FROM lehre.tbl_projektarbeit @@ -158,15 +157,17 @@ class Projektarbeit_model extends DB_Model LEFT JOIN public.tbl_benutzer USING(person_id) LEFT JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz) LEFT JOIN lehre.tbl_betreuerart USING(betreuerart_kurzbz) - LEFT JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) - LEFT JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) - LEFT JOIN public.tbl_mitarbeiter ON(public.tbl_mitarbeiter.mitarbeiter_uid = public.tbl_benutzer.uid) - LEFT JOIN public.tbl_studiengang USING(studiengang_kz) - WHERE - tbl_projektarbeit.student_uid = ? AND + LEFT JOIN lehre.tbl_lehreinheit USING(lehreinheit_id) + LEFT JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id) + LEFT JOIN public.tbl_mitarbeiter ON(public.tbl_mitarbeiter.mitarbeiter_uid = public.tbl_benutzer.uid) + LEFT JOIN public.tbl_studiengang USING(studiengang_kz) + LEFT JOIN lehre.tbl_note ON(lehre.tbl_projektarbeit.note = lehre.tbl_note.note) + WHERE + tbl_projektarbeit.student_uid = ? AND mitarbeiter_uid IS NOT NULL AND (projekttyp_kurzbz='Bachelor' OR projekttyp_kurzbz='Diplom') - AND betreuerart_kurzbz IN ('Betreuer', 'Begutachter', 'Erstbegutachter', 'Senatsvorsitz')"; - + AND betreuerart_kurzbz IN ('Betreuer', 'Begutachter', 'Erstbegutachter', 'Senatsvorsitz')) as base + ORDER BY insertamum DESC"; + return $this->execReadOnlyQuery($betreuerQuery, array($studentUID)); } @@ -179,8 +180,12 @@ 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_allowed, + campus.tbl_paabgabe.beurteilungsnotiz, campus.tbl_paabgabetyp.paabgabetyp_kurzbz, campus.tbl_paabgabetyp.bezeichnung, + campus.tbl_paabgabetyp.benotbar, campus.tbl_paabgabe.abgabedatum, campus.tbl_paabgabe.insertvon FROM campus.tbl_paabgabe JOIN campus.tbl_paabgabetyp USING(paabgabetyp_kurzbz) @@ -190,16 +195,54 @@ class Projektarbeit_model extends DB_Model return $this->execReadOnlyQuery($qry, array($projektarbeit_id)); } + public function getProjektarbeitenAbgabetermine($projektarbeiten_ids) { + $qry ="SELECT campus.tbl_paabgabe.paabgabe_id, + campus.tbl_paabgabe.projektarbeit_id, + campus.tbl_paabgabe.fixtermin, + campus.tbl_paabgabe.kurzbz, + campus.tbl_paabgabe.datum, + campus.tbl_paabgabe.note, + campus.tbl_paabgabe.upload_allowed, + campus.tbl_paabgabe.beurteilungsnotiz, + campus.tbl_paabgabetyp.paabgabetyp_kurzbz, + campus.tbl_paabgabetyp.bezeichnung, + campus.tbl_paabgabe.abgabedatum, + campus.tbl_paabgabe.insertvon + FROM campus.tbl_paabgabe JOIN campus.tbl_paabgabetyp USING(paabgabetyp_kurzbz) + WHERE campus.tbl_paabgabe.projektarbeit_id IN ? + ORDER BY campus.tbl_paabgabe.datum"; + + return $this->execReadOnlyQuery($qry, array($projektarbeiten_ids)); + } + public function getProjektbetreuerAnrede($bperson_id) { - $qry_betr="SELECT distinct trim(COALESCE(titelpre,'')||' '||COALESCE(vorname,'')||' '||COALESCE(nachname,'')||' '||COALESCE(titelpost,'')) as first, - public.tbl_mitarbeiter.mitarbeiter_uid, anrede - FROM public.tbl_person JOIN lehre.tbl_projektbetreuer ON(lehre.tbl_projektbetreuer.person_id=public.tbl_person.person_id) - JOIN public.tbl_benutzer ON(public.tbl_benutzer.person_id=public.tbl_person.person_id) - JOIN public.tbl_mitarbeiter ON(public.tbl_benutzer.uid=public.tbl_mitarbeiter.mitarbeiter_uid) - WHERE public.tbl_person.person_id= ?"; + $qry_betr="SELECT DISTINCT ON(public.tbl_person.person_id) trim(COALESCE(titelpre,'')||' '||COALESCE(vorname,'')||' '||COALESCE(nachname,'')||' '||COALESCE(titelpost,'')) as first, anrede + FROM public.tbl_person JOIN lehre.tbl_projektbetreuer ON(lehre.tbl_projektbetreuer.person_id=public.tbl_person.person_id) + 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, mitarbeiter_uid as uid + 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) { @@ -235,8 +278,8 @@ 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_benutzer.uid, tbl_student.matrikelnr, tbl_lehreinheit.studiensemester_kurzbz + 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, public.tbl_student.student_uid FROM lehre.tbl_projektarbeit LEFT JOIN lehre.tbl_projektbetreuer using(projektarbeit_id) LEFT JOIN lehre.tbl_betreuerart using(betreuerart_kurzbz) @@ -273,7 +316,134 @@ class Projektarbeit_model extends DB_Model return $this->execReadOnlyQuery($qry, array($projektarbeit_id)); } - + + + public function getProjektarbeitenForStudiengang($studiengang_kz, $benotet) { + $new_qry = "SELECT DISTINCT ON(tmp.projektarbeit_id) *, campus.get_betreuer_details(tmp.zweitbetreuer_person_id) as zweitbetreuer_full_name, campus.get_betreuer_details(tmp.betreuer_person_id) as erstbetreuer_full_name + FROM( + SELECT + DISTINCT ON(tbl_projektarbeit.projektarbeit_id) + tbl_projektarbeit.projekttyp_kurzbz, + tbl_projektarbeit.titel, + tbl_projektarbeit.projektarbeit_id, + tbl_studiengang.typ, tbl_studiengang.kurzbz, + student_benutzer.uid as student_uid, + student_person.vorname as student_vorname, + student_person.nachname as student_nachname, + tbl_student.matrikelnr, tbl_lehreinheit.studiensemester_kurzbz, + betreuer_benutzer.uid as betreuer_benutzer_uid, + betreuer_person.vorname as betreuer_vorname, + betreuer_person.nachname as betreuer_nachname, + lehre.tbl_projektbetreuer.betreuerart_kurzbz as betreuerart, + lehre.tbl_projektbetreuer.person_id as betreuer_person_id, + lehre.tbl_projektarbeit.sprache as sprache, + lehre.tbl_projektarbeit.seitenanzahl as seitenanzahl, + lehre.tbl_projektarbeit.kontrollschlagwoerter as kontrollschlagwoerter, + lehre.tbl_projektarbeit.schlagwoerter as schlagwoerter, + lehre.tbl_projektarbeit.schlagwoerter_en as schlagwoerter_en, + lehre.tbl_projektarbeit.abstract as abstract, + lehre.tbl_projektarbeit.abstract_en as abstract_en, + lehre.tbl_projektarbeit.insertamum as insertamum, + lehre.tbl_projektarbeit.note as note, + ( + SELECT orgform_kurzbz + FROM tbl_prestudentstatus + WHERE prestudent_id = (SELECT prestudent_id + FROM tbl_student + WHERE student_uid = student_benutzer.uid + LIMIT 1) + ORDER BY datum DESC, insertamum DESC, ext_id DESC + LIMIT 1 + ) + as organisationsform, + ( + SELECT person_id + FROM lehre.tbl_projektbetreuer + WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter', 'Senatsmitglied') + LIMIT 1 + ) + AS zweitbetreuer_person_id, + ( + SELECT betreuerart_kurzbz + FROM lehre.tbl_projektbetreuer + WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter', 'Senatsmitglied') + LIMIT 1 + ) + AS zweitbetreuer_betreuerart_kurzbz, + ( + SELECT tbl_betreuerart.beschreibung + FROM lehre.tbl_projektbetreuer + JOIN lehre.tbl_betreuerart USING (betreuerart_kurzbz) + WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter', 'Senatsmitglied') + LIMIT 1 + ) + AS zweitbetreuer_betreuerart_beschreibung, + ( + SELECT trim(COALESCE(titelpre, '') || ' ' || COALESCE(vorname, '') || ' ' || COALESCE(nachname, '') || ' ' || + COALESCE(titelpost, '')) + FROM public.tbl_person + JOIN lehre.tbl_projektbetreuer ON (lehre.tbl_projektbetreuer.person_id = public.tbl_person.person_id) + LEFT JOIN public.tbl_benutzer ON (public.tbl_benutzer.person_id = public.tbl_person.person_id) + LEFT JOIN public.tbl_mitarbeiter ON (public.tbl_benutzer.uid = public.tbl_mitarbeiter.mitarbeiter_uid) + WHERE projektarbeit_id = tbl_projektarbeit.projektarbeit_id + AND betreuerart_kurzbz IN ('Zweitbetreuer', 'Zweitbegutachter', 'Senatsmitglied') + LIMIT 1 + ) + as zweitbetreuer_full_name, + ( + SELECT + COALESCE(tbl_studienplan.orgform_kurzbz, + tbl_prestudentstatus.orgform_kurzbz, tbl_studiengang.orgform_kurzbz) as + orgform + FROM + public.tbl_prestudent + JOIN public.tbl_prestudentstatus USING(prestudent_id) + JOIN public.tbl_studiensemester USING(studiensemester_kurzbz) + JOIN public.tbl_studiengang USING(studiengang_kz) + LEFT JOIN lehre.tbl_studienplan USING(studienplan_id) + WHERE + prestudent_id=tbl_student.prestudent_id + ORDER BY tbl_prestudentstatus.datum DESC LIMIT 1 + ) as orgform, + (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 studienstatus + FROM lehre.tbl_projektarbeit + LEFT JOIN public.tbl_benutzer student_benutzer ON (student_benutzer.uid = lehre.tbl_projektarbeit.student_uid) + LEFT JOIN public.tbl_person student_person ON (student_benutzer.person_id = student_person.person_id) + LEFT JOIN public.tbl_student on(student_benutzer.uid = public.tbl_student.student_uid) + LEFT JOIN lehre.tbl_lehreinheit USING (lehreinheit_id) + LEFT JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id) + LEFT JOIN public.tbl_studiengang ON (public.tbl_student.studiengang_kz = public.tbl_studiengang.studiengang_kz) + LEFT JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz) + LEFT JOIN lehre.tbl_projektbetreuer USING (projektarbeit_id) + LEFT JOIN public.tbl_person betreuer_person ON (betreuer_person.person_id = lehre.tbl_projektbetreuer.person_id) + LEFT JOIN public.tbl_benutzer betreuer_benutzer ON (betreuer_person.person_id = betreuer_benutzer.person_id) + WHERE (projekttyp_kurzbz = 'Bachelor' OR projekttyp_kurzbz = 'Diplom') + AND student_benutzer.aktiv AND ( + lehre.tbl_projektbetreuer.betreuerart_kurzbz = 'Erstbegutachter' + OR lehre.tbl_projektbetreuer.betreuerart_kurzbz = 'Begutachter' + OR lehre.tbl_projektbetreuer.betreuerart_kurzbz = 'Betreuer' + OR lehre.tbl_projektbetreuer.betreuerart_kurzbz = 'Erstbetreuer' + OR lehre.tbl_projektbetreuer.betreuerart_kurzbz = 'Senatsvorsitz' + ) + AND public.tbl_studiengang.studiengang_kz = ?"; + + if($benotet == 0) { + $new_qry .= " AND lehre.tbl_projektarbeit.note IS NULL "; + } else if ($benotet == 1) { + $new_qry .= " AND lehre.tbl_projektarbeit.note IS NOT NULL "; + } + + $new_qry .= " ORDER BY tbl_projektarbeit.projektarbeit_id DESC, student_person.nachname ASC + ) as tmp"; + + return $this->execReadOnlyQuery($new_qry, array($studiengang_kz)); + } + /** * * @param @@ -299,4 +469,17 @@ class Projektarbeit_model extends DB_Model return false; } + + public function getProjektarbeitByPaabgabeID($paabgabe_id) { + $qry = "SELECT + projektarbeit_id + FROM + campus.tbl_paabgabe + JOIN lehre.tbl_projektarbeit USING(projektarbeit_id) + WHERE + campus.tbl_paabgabe.paabgabe_id = ?; + "; + + return $this->execReadOnlyQuery($qry, [$paabgabe_id]); + } } diff --git a/application/models/education/Projektbetreuer_model.php b/application/models/education/Projektbetreuer_model.php index 02368ae21..47e0239d6 100644 --- a/application/models/education/Projektbetreuer_model.php +++ b/application/models/education/Projektbetreuer_model.php @@ -232,4 +232,41 @@ class Projektbetreuer_model extends DB_Model return $this->execQuery($qry, array($projektarbeit_id, $betreuer_person_id)); } + + /** + * Gets all Betreuer of a Projektarbeit. + * Returns one row for each person. + * @param int $projektarbeit_id + * @return array success with number of Betreuer or error + */ + public function getAllBetreuerOfProjektarbeit($projektarbeit_id) + { + $qry = "SELECT DISTINCT ON (pers.person_id) pers.person_id, betreuerart_kurzbz, vorname, nachname, + trim(COALESCE(titelpre,'')||' '||COALESCE(vorname,'')||' '||COALESCE(nachname,'')||' '||COALESCE(titelpost,'')) as voller_name, + anrede, titelpre, titelpost, gebdatum, geschlecht, pa.projekttyp_kurzbz, + ben.uid, ben.alias, ma.personalnummer, mitarbeiter_uid, student_uid, + ( + 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 = ? + ORDER BY pers.person_id, CASE WHEN ma.mitarbeiter_uid IS NULL THEN 1 ELSE 0 END, /*Mitarbeiter account first*/ + CASE WHEN ben.uid IS NULL THEN 1 ELSE 0 END, /*user with account first*/ + ben.insertamum"; + + return $this->execQuery($qry, array($projektarbeit_id)); + } + } diff --git a/application/models/organisation/Organisationseinheit_model.php b/application/models/organisation/Organisationseinheit_model.php index db56c1930..9f64580a9 100644 --- a/application/models/organisation/Organisationseinheit_model.php +++ b/application/models/organisation/Organisationseinheit_model.php @@ -243,4 +243,20 @@ class Organisationseinheit_model extends DB_Model return $this->execReadOnlyQuery($qry, array($oe_kurzbz)); } + + public function getAssistenzForOE($oe_kurzbz) { + $qry = " + SELECT person_id, uid, benutzerfunktion_id, funktion_kurzbz, oe_kurzbz, alias, + anrede, trim(COALESCE(titelpre,'')||' '||COALESCE(vorname,'')||' '||COALESCE(nachname,'')||' '||COALESCE(titelpost,'')) as first + FROM tbl_benutzerfunktion + JOIN public.tbl_benutzer USING(uid) + JOIN public.tbl_person USING(person_id) + WHERE funktion_kurzbz = 'ass' + AND oe_kurzbz = ? + AND (datum_bis IS NULL OR NOW() <= datum_bis) + AND public.tbl_benutzer.aktiv = true + "; + + return $this->execReadOnlyQuery($qry, array($oe_kurzbz)); + } } diff --git a/application/models/organisation/Studiengang_model.php b/application/models/organisation/Studiengang_model.php index 02f972690..131e1deb5 100644 --- a/application/models/organisation/Studiengang_model.php +++ b/application/models/organisation/Studiengang_model.php @@ -657,37 +657,7 @@ class Studiengang_model extends DB_Model $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); $this->load->model('person/Person_model', 'PersonModel'); $this->load->model('crm/Student_model', 'StudentModel'); - - $addEmailProperty= function(&$benutzerfunktionen){ - if(count($benutzerfunktionen) && defined('DOMAIN')) - { - $benutzerfunktionen = array_map(function($benutzer) - { - $benutzer->email = $benutzer->alias."@".DOMAIN; - return $benutzer; - },$benutzerfunktionen) ; - } - - }; - $addFotoProperty= function(&$collection){ - $collection = array_map(function($item){ - $person_id = $this->PersonModel->getByUid($item->uid); - if(isError($person_id)) - return error($person_id); - $person_id = current(getData($person_id))->person_id; - $this->PersonModel->addSelect('foto'); - $foto = $this->PersonModel->loadWhere(array('person_id'=>$person_id)); - if(isError($foto)) - return error($foto); - $foto = current(getData($foto))->foto; - $item->foto = $foto; - return $item; - },$collection); - }; - - $this->load->model('crm/Student_model', 'StudentModel'); - $student = $this->StudentModel->loadWhere(['student_uid' => getAuthUID()]); if (isError($student)) return error($student); @@ -712,7 +682,7 @@ class Studiengang_model extends DB_Model $stg_ltg = array_values(array_filter($stg_ltg, function($stg_leitung){ return $stg_leitung->aktiv; })); - $addFotoProperty($stg_ltg); + $this->addFotoProperty($stg_ltg); $gf_ltg = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('gLtg', $stg_obj->oe_kurzbz); if (isError($gf_ltg)) @@ -721,8 +691,8 @@ class Studiengang_model extends DB_Model $gf_ltg = array_values(array_filter($gf_ltg, function($gf_leitung){ return $gf_leitung->aktiv; })); - $addEmailProperty($gf_ltg); - $addFotoProperty($gf_ltg); + $this->addEmailProperty($gf_ltg); + $this->addFotoProperty($gf_ltg); $stv_ltg = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('stvLtg', $stg_obj->oe_kurzbz); if (isError($stv_ltg)) @@ -731,8 +701,8 @@ class Studiengang_model extends DB_Model $stv_ltg = array_values(array_filter($stv_ltg, function($stv_leitung){ return $stv_leitung->aktiv; })); - $addEmailProperty($stv_ltg); - $addFotoProperty($stv_ltg); + $this->addEmailProperty($stv_ltg); + $this->addFotoProperty($stv_ltg); $ass = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('ass', $stg_obj->oe_kurzbz); if (isError($ass)) @@ -741,8 +711,8 @@ class Studiengang_model extends DB_Model $ass = array_values(array_filter($ass, function($assistenz){ return $assistenz->aktiv; })); - $addEmailProperty($ass); - $addFotoProperty($ass); + $this->addEmailProperty($ass); + $this->addFotoProperty($ass); $hochschulvertr = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('hsv'); if (isError($hochschulvertr)) @@ -751,7 +721,7 @@ class Studiengang_model extends DB_Model $hochschulvertr = array_values(array_filter($hochschulvertr, function($hochschul_vertreter){ return $hochschul_vertreter->aktiv; })); - $addEmailProperty($hochschulvertr); + $this->addEmailProperty($hochschulvertr); $stdv = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('stdv', $stg_obj->oe_kurzbz); @@ -761,7 +731,7 @@ class Studiengang_model extends DB_Model $stdv = array_values(array_filter($stdv, function($std_vertreter){ return $std_vertreter->aktiv; })); - $addEmailProperty($stdv); + $this->addEmailProperty($stdv); $jahrgangsvertr = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('jgv', $stg_obj->oe_kurzbz, $semester); @@ -771,7 +741,7 @@ class Studiengang_model extends DB_Model $jahrgangsvertr = array_values(array_filter($jahrgangsvertr, function($jahrgang_vertreter){ return $jahrgang_vertreter->aktiv; })); - $addEmailProperty($jahrgangsvertr); + $this->addEmailProperty($jahrgangsvertr); $result_object = new stdClass(); @@ -801,4 +771,141 @@ class Studiengang_model extends DB_Model return $this->execReadOnlyQuery($qry, array($studiengang_kz, $orgform_kurzbz, $studiensemester_kurzbz)); } + + /** + * Get active Studiengänge with Kuerzel by given Studiengang-Kennzahlen. + * Helpful to easily get Studiengänge the user is entitled for. + * + * @param $studiengang_kz_arr + * @param $studiensemester_kurzbz + * @return array|stdClass|null Returns one row per Studiengang. Not considering the Orgforms. + */ + public function getByStgs($studiengang_kz_arr, $studiensemester_kurzbz) + { + if (is_numeric($studiengang_kz_arr)) + { + $studiengang_kz_arr = [$studiengang_kz_arr]; + } + + $qry = ' + SELECT + DISTINCT stg.*, UPPER(typ::varchar(1) || kurzbz) AS kuerzel + FROM + public.tbl_studiengang stg + JOIN lehre.tbl_studienordnung sto USING(studiengang_kz) + JOIN lehre.tbl_studienplan stpl USING(studienordnung_id) + JOIN lehre.tbl_studienplan_semester stplsem USING(studienplan_id) + WHERE + stg.studiengang_kz IN ? + AND stplsem.studiensemester_kurzbz = ? + ORDER BY + stg.kurzbzlang + '; + + return $this->execQuery($qry, [$studiengang_kz_arr, $studiensemester_kurzbz]); + } + + /** + * Get OrgForms of given Studiengang and Studiensemester. + * + * @param $studiengang_kz + * @param $studiensemester_kurzbz + * @return array|stdClass|null + */ + public function getOrgformsByStg($studiengang_kz, $studiensemester_kurzbz) + { + $qry = ' + SELECT + stpl.orgform_kurzbz + FROM + public.tbl_studiengang stg + JOIN lehre.tbl_studienordnung sto USING(studiengang_kz) + JOIN lehre.tbl_studienplan stpl USING(studienordnung_id) + JOIN lehre.tbl_studienplan_semester stplsem USING(studienplan_id) + WHERE + stg.studiengang_kz = ? + AND stg.aktiv = TRUE + AND stplsem.studiensemester_kurzbz = ? + GROUP BY + stpl.orgform_kurzbz + ORDER BY + CASE stpl.orgform_kurzbz + WHEN \'VZ\' THEN 1 + WHEN \'BB\' THEN 2 + WHEN \'DUA\' THEN 3 + ELSE 4 + END, + stpl.orgform_kurzbz; + '; + + return $this->execQuery($qry, [$studiengang_kz, $studiensemester_kurzbz]); + } + + public function getStudiengaengeFiltered($allowed_stg) { + $query ="SELECT DISTINCT + public.tbl_studiengang.studiengang_kz, + public.tbl_studiengang.bezeichnung, + public.tbl_studiengang.kurzbzlang, + public.tbl_studiengang.orgform_kurzbz + FROM public.tbl_studiengang JOIN lehre.tbl_studienordnung USING(studiengang_kz) + JOIN lehre.tbl_studienplan USING(studienordnung_id) + JOIN lehre.tbl_studienplan_semester USING(studienplan_id) + WHERE public.tbl_studiengang.aktiv = true + + AND public.tbl_studiengang.studiengang_kz IN ? + ORDER BY public.tbl_studiengang.kurzbzlang"; + + return $this->execReadOnlyQuery($query, [$allowed_stg]); + } + + public function getAssistenzForStudiengangKZ($stg_kz) { + $this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + + $stg_obj = $this->load($stg_kz); + if(isError($stg_obj)) + return error($stg_obj); + if(getData($stg_obj)) + { + $stg_obj = current(getData($stg_obj)); + } + + $ass = $this->BenutzerfunktionModel->getBenutzerFunktionenDetailed('ass', $stg_obj->oe_kurzbz); + if (isError($ass)) + return $ass; + $ass = getData($ass) ?: []; + $ass = array_values(array_filter($ass, function($assistenz){ + return $assistenz->aktiv; + })); + + $this->addEmailProperty($ass); + + return success($ass); + } + + private function addEmailProperty(&$benutzerfunktionen) { + if(count($benutzerfunktionen) && defined('DOMAIN')) + { + $benutzerfunktionen = array_map(function($benutzer) + { + $benutzer->email = $benutzer->alias."@".DOMAIN; + return $benutzer; + },$benutzerfunktionen) ; + } + } + + private function addFotoProperty (&$collection) { + $collection = array_map(function($item){ + $person_id = $this->PersonModel->getByUid($item->uid); + if(isError($person_id)) + return error($person_id); + $person_id = current(getData($person_id))->person_id; + $this->PersonModel->addSelect('foto'); + $foto = $this->PersonModel->loadWhere(array('person_id'=>$person_id)); + if(isError($foto)) + return error($foto); + $foto = current(getData($foto))->foto; + $item->foto = $foto; + return $item; + },$collection); + } } diff --git a/application/models/ressource/Stundenplan_model.php b/application/models/ressource/Stundenplan_model.php index 389be582d..067e2b790 100644 --- a/application/models/ressource/Stundenplan_model.php +++ b/application/models/ressource/Stundenplan_model.php @@ -535,4 +535,53 @@ class Stundenplan_model extends DB_Model return $this->execQuery($query, [$uid, $uid]); } + + /** + * Get Stundenplantermine for given Lehreinheit. + * + * @param $lehreinheit_id + * @return array|stdClass|null + */ + public function getTermineByLe($lehreinheit_id) + { + $qry = ' + SELECT DISTINCT + datum + FROM + lehre.vw_stundenplan + WHERE + lehreinheit_id = ? + ORDER BY + datum ASC + '; + + return $this->execQuery($qry, [$lehreinheit_id]); + } + + /** + * Get Stundenplantermine for given Lehrveranstaltung of given Studiensemester. + * + * @param $lehrveranstaltung_id + * @param $studiensemester_kurzbz + * @return array|stdClass|null + */ + public function getTermineByLv($lehrveranstaltung_id, $studiensemester_kurzbz) + { + $qry = ' + SELECT DISTINCT + datum + FROM + lehre.vw_stundenplan + WHERE + lehreinheit_id IN ( + SELECT lehreinheit_id + FROM lehre.tbl_lehreinheit + WHERE lehrveranstaltung_id = ? + AND studiensemester_kurzbz = ? + ) + ORDER BY datum ASC + '; + + return $this->execQuery($qry, [$lehrveranstaltung_id, $studiensemester_kurzbz]); + } } diff --git a/application/phrases/abgabetool.php b/application/phrases/abgabetool.php index ddafabb43..6d1f2a8d2 100644 --- a/application/phrases/abgabetool.php +++ b/application/phrases/abgabetool.php @@ -1071,4 +1071,2828 @@ array ( ), ), ) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4Sprache', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Sprache', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Language', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4fehlerAktualitaetProjektarbeit ', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Projektarbeit ist nichtmehr aktuell', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Project work is not current anymore', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'keinTitel', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Kein Titel', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'No Title', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4abgabeuntil2359', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Abgabe bis 23:59', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Submission until 23:59', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4fixterminv4', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Nachreichen möglich', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'late submission possible', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4orgform', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Organisationseinheit', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'organization unit', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4studstatus', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Studierendenstatus', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'student status', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4signaturGefunden', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Digitale Signatur gefunden', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'digital signature found', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4keineSignatur', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Keine Digitale Signatur gefunden', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'no digital signature found', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4signaturServerError', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Signatur Server Error', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'signature server error', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4noFileFound', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Datei wurde nicht gefunden', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'file not found', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4fileUploaded', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Datei hochgeladen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'file uploaded', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4actions', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Aktionen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'actions', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4aeltereParbeitBenotenv2', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Projektarbeit für älteres Semester, bitte Word-Formular in Moodle zur Benotung verwenden!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Thesis handed in for older semester, please use word form in moodle for assessment!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4keinEnduploadErfolgt', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Endupload ist noch nicht erfolgt', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Final version not uploaded yet', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4benoten', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Benoten', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Grade', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4save', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Speichern', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Save', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4delete', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Löschen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Delete', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4note', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Note', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Grade', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4upload_allowed', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Upload erlaubt', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Upload allowed', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4student_perspective', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Studierendenansicht', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Student perspective', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4plagiatcheck_link', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'zur Plagiatsprüfung', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Plagiarism check', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4noEnduploadFound', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Kein Endupload vorhanden!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'No final submission found!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4notizQualGatev2', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Beurteilungsnotizen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Evaluation notes', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4abgabeMitarbeiterDetailTitle', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Projektarbeit Detailansicht MitarbeiterIn', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Project work Detailed view Employees', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4abgabeStudentDetailTitle', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Projektarbeit Detailansicht Studierende', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Project work Detailed view Students', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4tooltipVerspaetet', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Verspätet abgegeben', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Submitted late', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4tooltipBeurteilungerforderlich', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Beurteilung erforderlich', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Grading necessary', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4tooltipBestanden', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Bestanden', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'passed', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4tooltipNichtBestanden', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Nicht Bestanden', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'not passed', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4tooltipVerpasst', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Termin überschritten', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Deadline exceeded', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4tooltipAbzugeben', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Termin innerhalb von 12 Tagen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Deadline within 12 days', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4tooltipStandardv2', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Termin mehr als 12 Tage entfernt', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Deadline more than 12 days away', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4tooltipAbgegeben', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Rechtzeitig abgegeben', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Delivered on time', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4tooltipFixtermin', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Für den gesamten Studiengang verbindlicher Termin. + + Liegt ein Termin in der Vergangenheit, kann nichts mehr hochgeladen werden. Ist es dennoch erforderlich, + haben Studierende bei der Studiengangsassistenz um eine Korrektur dieses Termins anzusuchen.', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'This deadline is binding for the entire program. If a deadline is in the past, + nothing can be uploaded. If it is still necessary, + students must request a correction of this deadline from the program assistant.', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4tooltipAbgabeDetected', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Zu diesem Abgabetermin wurde bereits eine Datei hochgeladen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'a file has been uploaded for this deadline', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4tapForTooltipInfo', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Tippen Sie für Tooltip-Informationen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'tap for tooltip information', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4abgabeZeitstatus', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Zeitstatus', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'time status', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4notAllowedToEditAbgabeTermin', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Sie sind nicht berechtigt diesen Abgabetermin zu bearbeiten. + Es muss entweder eine Benotung vorgesehen sein oder sich um einen individuellen Termin handeln, + welcher von Ihrem Benutzerkonto angelegt wurde.', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'You are not authorized to edit this deadline. + It must either be scheduled for grading or be a custom due date + created by your user account.', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4notAllowedToDeleteAbgabeTermin', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Sie sind nicht berechtigt diesen Abgabetermin zu löschen. + Sie benötigen mindestens die Berechtigung den Termin zu bearbeiten und es darf noch keine + Dateiabgabe vorhanden sein.', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'You are not authorized to delete this deadline. + You need at least the permission to edit the deadline, and no file submissions must yet exist.', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4ZusatzdatenBearbeiten', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Zusatzdaten bearbeiten', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Edit additional data', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4abgabeStudentNoProjectsFound', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Keine Projektarbeiten gefunden!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'No projects found!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4studentAbgabeNotAllowedInViewMode', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Projektabgabe im Ansichtsmodus ist nicht erlaubt!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Project submission in view mode is not allowed!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4studentAbgabeNotAllowedRegular', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Verspätete Projektabgabe ist bei Terminen, welche von der Studiengangsassistenz für den gesamten Studiengang fixiert wurden nicht erlaubt! + + Um einen Endupload durchführen zu können, müssen Sie ein positiv benotetes Quality Gate 1 & Quality Gate 2 in der relevanten Projektarbeit absolviert haben.', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Late project submissions are not permitted for deadlines set by the program assistant for the entire program! + + To be able to complete a final upload, you must have successfully completed Quality Gate 1 and Quality Gate 2 for the relevant project work.', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4benotet', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Benotet', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Graded', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4confirm_delete', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Möchten Sie wirklich Löschen?', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Do you really want to delete?', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4nochNichtsAbgegeben', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Keine Abgabe vorhanden', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'No submission yet', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4newAbgabetermin', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Neuen Abgabetermin erstellen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Create new Deadline', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4qualgateNegativEmailSubjectv2', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Quality Gate negativ beurteilt', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Quality Gate graded negative', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4noGradeAssignedYet', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Keine Note eingetragen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'no grade assigned yet', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4abgabeQualGateNegativAddNewAutomagisch', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Sie haben eine Abgabe vom Typ Quality Gate negativ benotet, bitte legen Sie zeitnah einen Nachfolgetermin an!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'You have graded a submission of type Quality Gate negative, please schedule a follow-up appointment promptly!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4betreuerEmailKontakt', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'E-Mail BetreuerIn', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Email Assessor', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4projektdetailsOeffnen', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Projektdetails öffnen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'open Project Details', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4downloadBeurteilungErstbetreuer', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'ErstbetreuerIn Beurteilung herunterladen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Download evaluation of first assesor', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4downloadBeurteilungZweitbetreuer', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'ZweitbetreuerIn Beurteilung herunterladen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Download evaluation of second assesor', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4nobeurteilungVorhanden', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Keine Beurteilung vorhanden', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'No Project evaluation found', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4AcceptAndProceed', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Akzeptieren und Fortfahren', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Accept and proceed', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4Cancel', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Abbrechen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Cancel', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4downloadAbgabe', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Abgabe herunterladen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Download File', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'confirmEnduploadSpeichern', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Möchten Sie den Endupload durchführen?', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Do you want to complete the final upload?', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'confirmZusatzdatenSpeichern', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Möchten Sie die Zusatzdaten speichern?', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Do you want to save the additional data?', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4errorLoadingStudentForProjektarbeitID', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Fehler beim Laden der Projektarbeit - StudentIn Zuordnung', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Error loading student for project work', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4noAssignedStudentForProjektarbeitID', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Kein zugeteilter StudentIn gefunden für Projektarbeit', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'No assigned student found for project work', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4zusatzdatenausfuellen', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Alle Zusatzdatenfelder benötigen Eingabewerte!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'All additional data fields are required!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'warningShortAbstract', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Ihr Abstract ist sehr kurz, möchten Sie den Endupload trotzdem durchführen?', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Your abstract is very short. Would you still like to complete the final upload?', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'warningShortAbstractEn', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Ihr englisches Abstract ist sehr kurz, möchten Sie den Endupload trotzdem durchführen?', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Your english abstract is very short. Would you still like to complete the final upload?', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'warningShortSchlagwoerter', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Ihre Schlagwörter sind sehr kurz, möchten Sie den Endupload trotzdem durchführen?', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Your keywords are very short. Would you still like to complete the final upload?', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'warningShortSchlagwoerterEn', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Ihre englischen Schlagwörter sind sehr kurz, möchten Sie den Endupload trotzdem durchführen?', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Your english keywords are very short. Would you still like to complete the final upload?', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'warningSmallSeitenanzahl', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Ihre Seitenanzahl ist gering, möchten Sie den Endupload trotzdem durchführen?', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Your number of pages is low. Would you still like to complete the final upload?', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4saveNewAbgabetermin', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Neuen Abgabetermin speichern', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Save new Deadline', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4fileUploadSuccessv3', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Datei erfolgreich hochgeladen!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'File upload successful', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4fileUploadErrorv3', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Fehler beim hochladen der Datei!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'File upload error!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4prevAbgabetermin', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Vorheriger Termin', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Previous Deadline', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4nextAbgabetermin', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Nächster Termin', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Next Deadline', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4erstbetreuer', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'ErstbetreuerIn', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'First Assessor', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4zweitbetreuer', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'ZweitbetreuerIn', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Second Assessor', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4projektarbeitTimelineTitle', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Projektarbeit Abgabetermine Zeitstrahl', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Project Deadline Timeline', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4sendEmailStudierende', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Email an Studierende schicken', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Send Email to students', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4sendEmailBetreuer', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Email an Betreuende schicken', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Send Email to assessors', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4keineAbgabetermineGefunden', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Die Projektarbeit hat keine zugeordneten Abgabetermine!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Project has no assigned Deadlines!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'showStudentDetails', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Studierende Details anzeigen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'show student details', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'keineNoteEingetragen', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Keine Note eingetragen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Not graded yet', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4fehlerMailBegutachter', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Fehler beim Versenden des Mails an den Erstbegutachter!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Error sending E-Mail to first Assessor!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4fehlerMailZweitBegutachter', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Fehler beim Versenden des Mails an den Zweitbegutachter!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Error sending E-Mail to second Assessor!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4projektarbeitNichtGefunden', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Keine Projektarbeit gefunden.', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'No projekt work has been found.', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4projektabgabeNichtGefunden', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Keine Projektabgabe gefunden.', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'No projekt deadline has been found.', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4userNichtGefunden', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'User nicht gefunden.', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'User not found.', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'changedAbgabeterminev2', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Updates: Abgabetermine Bachelor-/Masterarbeiten', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Updates: Deadlines Bachelor\'s-/Master\'s Thesis', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4paatypqualgate1', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Quality Gate 1', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Quality Gate 1', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4paatypqualgate2', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Quality Gate 2', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Quality Gate 2', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4paatypzwischen', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Zwischenabgabe', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Interim submission', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4paatypnote', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Benotung', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Grading', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4paatypabstract', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Entwurf', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Design', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4paatypend', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Endupload', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Final submission', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4paatypenda', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Endabgabe im Sekretariat', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Final submission in the administrative office', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4projtypBachelor', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Bachelorarbeit', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Bachelor\'s thesis', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4projtypProjekt', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Projektarbeit', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Project work', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4projtypPraktikum', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Praktikum', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Internship', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4projtypPraxis', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Praxissemester', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Practical semester', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4projtypDiplom', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Masterarbeit', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Master\'s thesis', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4betrartBegutachter', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'BegutachterIn Bachelorarbeit', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Reviewer bachelor\'s thesis', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4betrartErstbetreuer', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Erstbetreuer einer Diplomarbeit', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'First reviewer of a master\'s thesis', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4betrartErstbegutachter', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => '1. BegutachterIn Masterarbeit', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => '1. reviewer master\'s thesis', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4betrartZweitbegutachter', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => '2. BegutachterIn Masterarbeit', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => '2. reviewer master\'s thesis', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4betrartzweitbetreuer', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Zweitbetreuer einer Diplomarbeit', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Second reviewer of a master\'s thesis', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4betrartBetreuer', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'BetreuerIn Berufspraktikum oder Projektarbeit', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Reviewer of an internship or project work', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4betrartSenatsvorsitz', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Vorsitz Prüfungssenat', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Chair of examination board', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4betrartSenatsmitglied', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Mitglied Prüfungssenat', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Member of examination board', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4qgate1Status', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Status QG1', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Status QG1', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4qgate2Status', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Status QG2', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Status QG2', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4keinTerminVorhanden', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Kein Termin vorhanden', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'No Deadline found', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4checkoutStgMoodleInfos', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Für weitere Information zu den Abgabemodalitäten Ihres Studienganges lesen Sie bitte die Unterlagen in Moodle: ', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'For further information on the submission procedures for your degree program, please refer to the documents in Moodle: ', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4positivBenotet', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Positiv Benotet!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Graded positive!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4negativBenotet', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Negativ Benotet!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Graded negative!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4notYetGraded', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Noch nicht beurteilt', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Not graded yet', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4notSubmitted', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Noch nicht abgegeben', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Not submitted yet', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'abgabetool', + 'phrase' => 'c4notHappenedYet', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Noch nicht stattgefunden', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Not happened yet', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) ); diff --git a/application/phrases/fragebogen.php b/application/phrases/fragebogen.php new file mode 100644 index 000000000..383587792 --- /dev/null +++ b/application/phrases/fragebogen.php @@ -0,0 +1,531 @@ + 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'loginTextCodeEingeben', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Bitte geben Sie Ihren Code ein, um die Evaluierung zu starten:', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + 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 ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Evaluierung-Code eingeben', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Enter your Evaluation-Code', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'loginTextLvevaluierung', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => ' +
+

Die folgende LV-Evaluierung umfasst

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

The following course evaluation includes

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

Die Antwortoptionen umfassen 5 Stufen:

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

The answer options comprise 5 levels:

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

Danke, dass Sie sich Zeit für das Feedback genommen haben! Ihre ehrliche und konstruktive Rückmeldung ist essenziell, damit Ihre Lehrenden und Ihre Studiengangsleitung die Lehrveranstaltung immer weiter verbessern und anpassen können!

+

Und was passiert jetzt mit Ihrem Feedback? Die Studiengangsleitung wird die Ergebnisse & Maßnahmen zusammen mit Ihrer Jahrgangsvertretung besprechen. So tragen Sie aktiv dazu bei, die Lehrveranstaltung für zukünftige Semester noch spannender & lehrreicher zu machen!

+

Gemeinsam für mehr Qualität in der Lehre!

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

Thank you for taking the time to provide feedback! Your honest and constructive input is essential for your lecturers and degree program director to continuously improve and adapt the course.

+

What happens with your feedback? The degree program director will discuss the results and potential measures together with your academic year representatives. You have thus actively contributed to making the course even more engaging and educational for future semesters!

+

Working together for higher quality in teaching!

+ ', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungZeitAbgelaufen', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Die Evaluierungszeit ist abgelaufen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'The Evaluation time is over', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungAntwortenNichtUebermittelt', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Ihre Antworten wurden nicht übermittelt.', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Your responses were not submitted.', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungCodeExistiertNicht', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Dieser Evaluierungscode exisitiert nicht', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'This evaluation code does not exist', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungNichtAktiv', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Die Evaluierung ist nicht aktiv', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Evaluation is not active', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'zeitLaeuftAb', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Zeit läuft bald ab – zum Speichern bitte ‚Abschicken‘ klicken', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Time is running out — please click ‘Submit’ to save your answers', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'spracheAuswaehlen', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Sprache auswählen', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Select language', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'fhtwLogo', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'FH Technikum Wien Logo', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'UAS Technikum Wien Logo', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'evaluierungscodeEingeben', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Evaluierungscode eingeben', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Enter Evaluation code', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'lvevaluierung', + 'category' => 'fragebogen', + 'phrase' => 'pflichtantwortFehlt', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Pflichtantwort fehlt', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Mandatory answer missing', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +); \ No newline at end of file diff --git a/application/phrases/global.php b/application/phrases/global.php index 8f4781e33..31385bbfd 100644 --- a/application/phrases/global.php +++ b/application/phrases/global.php @@ -8779,5 +8779,101 @@ array ( ), ), ) +, +array ( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'filesizeExceeded', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Die maximale Dateigröße wurde überschritten!', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'The maximum file size has been exceeded!', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'abschicken', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Abschicken', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Submit', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'core', + 'category' => 'global', + 'phrase' => 'zurueckZumStart', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'Zurück zum Start', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Back to Start', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) +, +array ( + 'app' => 'lvevaluierung', + 'category' => 'global', + 'phrase' => 'lvevaluierungAbschicken', + 'insertvon' => 'system', + 'phrases' => + array ( + 0 => + array ( + 'sprache' => 'German', + 'text' => 'LV-Evaluierung abschicken', + 'description' => '', + 'insertvon' => 'system', + ), + 1 => + array ( + 'sprache' => 'English', + 'text' => 'Submit Course Evaluation', + 'description' => '', + 'insertvon' => 'system', + ), + ), +) ); diff --git a/application/views/Cis/Abgabetool.php b/application/views/Cis/Abgabetool.php new file mode 100644 index 000000000..480116290 --- /dev/null +++ b/application/views/Cis/Abgabetool.php @@ -0,0 +1,46 @@ + 'Cis4', + 'axios027' => true, + 'bootstrap5' => true, + 'fontawesome6' => true, + 'tabulator5' => true, // TODO: upgrade to 6 when available + 'vue3' => true, + 'primevue3' => true, + 'skipID' => '#fhccontent', + 'vuedatepicker11' => true, + 'customCSSs' => array( + 'public/css/components/verticalsplit.css', + 'public/css/components/FilterComponent.css', + 'public/css/components/FormUnderline.css', + 'public/css/theme/default.css', + 'public/css/components/abgabetool/abgabe.css' + ), + 'customJSs' => array( + 'vendor/npm-asset/primevue/accordion/accordion.min.js', + 'vendor/npm-asset/primevue/accordiontab/accordiontab.min.js', + 'vendor/npm-asset/primevue/checkbox/checkbox.min.js', + 'vendor/npm-asset/primevue/inputnumber/inputnumber.min.js', + 'vendor/npm-asset/primevue/speeddial/speeddial.min.js', + 'vendor/npm-asset/primevue/textarea/textarea.min.js', + 'vendor/npm-asset/primevue/timeline/timeline.min.js', + 'vendor/npm-asset/primevue/inplace/inplace.min.js', + 'vendor/npm-asset/primevue/message/message.min.js', + 'vendor/moment/luxonjs/luxon.min.js' + ), + 'customJSModules' => array( + 'public/js/apps/Abgabetool/Abgabetool.js', + ), + +); + +$this->load->view('templates/FHC-Header', $includesArray); +?> +
+ uid= + student_uid_prop="" + stg_kz_prop="" + > +
+load->view('templates/FHC-Footer', $includesArray); ?> diff --git a/application/views/CisRouterView/CisRouterView.php b/application/views/CisRouterView/CisRouterView.php index ab22fbb81..1b3e767b2 100644 --- a/application/views/CisRouterView/CisRouterView.php +++ b/application/views/CisRouterView/CisRouterView.php @@ -21,19 +21,24 @@ $includesArray = array( 'public/css/components/FilterComponent.css', 'public/css/components/Profil.css', 'public/css/components/FormUnderline.css', + 'public/css/components/abgabetool/abgabe.css', 'public/css/Cis4/Cms.css', 'public/css/Cis4/Studium.css', ), 'customJSs' => array( 'vendor/npm-asset/primevue/accordion/accordion.min.js', 'vendor/npm-asset/primevue/accordiontab/accordiontab.min.js', - 'vendor/npm-asset/primevue/inputnumber/inputnumber.min.js', - 'vendor/npm-asset/primevue/textarea/textarea.min.js', 'vendor/npm-asset/primevue/checkbox/checkbox.min.js', + 'vendor/npm-asset/primevue/inputnumber/inputnumber.min.js', + 'vendor/npm-asset/primevue/speeddial/speeddial.min.js', + 'vendor/npm-asset/primevue/textarea/textarea.min.js', + 'vendor/npm-asset/primevue/timeline/timeline.min.js', + 'vendor/npm-asset/primevue/inplace/inplace.min.js', + 'vendor/npm-asset/primevue/message/message.min.js', 'vendor/moment/luxonjs/luxon.min.js' ), 'customJSModules' => array( - 'public/js/apps/Dashboard/Fhc.js' + 'public/js/apps/Dashboard/Fhc.js', ), ); diff --git a/application/views/templates/CISVUE-Header.php b/application/views/templates/CISVUE-Header.php index 358fc75c9..804a43821 100644 --- a/application/views/templates/CISVUE-Header.php +++ b/application/views/templates/CISVUE-Header.php @@ -36,4 +36,4 @@ $this->load->view('templates/FHC-Header', $includesArray); > -
\ No newline at end of file +
\ No newline at end of file diff --git a/cis/testtool/externeueberwachung.js b/cis/testtool/externeueberwachung.js new file mode 100644 index 000000000..71951779f --- /dev/null +++ b/cis/testtool/externeueberwachung.js @@ -0,0 +1,15 @@ +(function () { + function sendMessage() { + let frame = window.frames['content']; + if (frame) + frame.postMessage({ type: "proctoringReady" }); + } + + window.addEventListener("message", function (e) + { + if (e.data.indexOf("proctoringReady_") === 0) + { + sendMessage(); + } + }); +})(); diff --git a/cis/testtool/frage.css b/cis/testtool/frage.css new file mode 100644 index 000000000..04024ae53 --- /dev/null +++ b/cis/testtool/frage.css @@ -0,0 +1,30 @@ +.proctoring-blocker +{ + position: fixed; + inset: 0; + z-index: 99999; + backdrop-filter: blur(6px); + pointer-events: all; + user-select: none; +} + +.proctoring-blocker.hidden +{ + display: none !important; +} + +.proctoring-text +{ + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: #fff; + font-size: 16px; + font-family: sans-serif; +} + +.proctoring-blur-fallback +{ + filter: blur(6px); +} diff --git a/cis/testtool/frage.php b/cis/testtool/frage.php index c38229cdf..bf2ee24c5 100644 --- a/cis/testtool/frage.php +++ b/cis/testtool/frage.php @@ -45,7 +45,7 @@ if (!$db = new basis_db()) $PHP_SELF=$_SERVER["PHP_SELF"]; // Start session -session_start(); +require_once './session_init.php'; // If language is changed by language select menu, reset language variables if (isset($_GET['sprache_user']) && !empty($_GET['sprache_user'])) @@ -182,6 +182,12 @@ echo ' if(!isset($_SESSION['pruefling_id'])) die($p->t('testtool/bitteZuerstAnmelden')); +if (!empty($_SESSION['externe_ueberwachung']) && isset($_SESSION['externe_ueberwachung_verified'])): ?> + + + +load($_SESSION['pruefling_id']); diff --git a/cis/testtool/frage_externe_ueberwachung.js b/cis/testtool/frage_externe_ueberwachung.js new file mode 100644 index 000000000..31a7b414f --- /dev/null +++ b/cis/testtool/frage_externe_ueberwachung.js @@ -0,0 +1,53 @@ +(function () { + let ok = false; + let blocker; + + function showBlocker() { + blocker = document.getElementById("proctoringBlocker"); + + if (!blocker) + { + blocker = document.createElement("div"); + blocker.id = "proctoringBlocker"; + blocker.className = "proctoring-blocker"; + blocker.innerHTML = '
Loading...
'; + document.body.appendChild(blocker); + } + document.documentElement.classList.add("proctoring-blur-fallback"); + } + + function block() { + showBlocker(); + blocker.classList.remove("hidden"); + } + + function unblock() { + document.documentElement.classList.remove("proctoring-blur-fallback"); + if (!blocker) return; + blocker.classList.add("hidden"); + } + + const blockTimer = setTimeout(function () { + if (!ok) + block(); + }, 1500); + + window.addEventListener("message", function (e) { + const data = e.data || {}; + + if (data.type === "proctoringReady") + { + ok = true; + clearTimeout(blockTimer); + unblock(); + } + }); + + setTimeout(function () { + if (!ok) { + top.location.href = "resetconnection.php"; + } + }, 3000); +})(); + + diff --git a/cis/testtool/index.php b/cis/testtool/index.php index d235e6ce9..6f2cfac26 100644 --- a/cis/testtool/index.php +++ b/cis/testtool/index.php @@ -1,16 +1,79 @@ TestTool - FH Technikum Wien + + + + @@ -26,3 +89,4 @@ if(isset($_GET['prestudent']) && is_numeric($_GET['prestudent'])) + diff --git a/cis/testtool/login.php b/cis/testtool/login.php index 5306dadab..d028a41ff 100644 --- a/cis/testtool/login.php +++ b/cis/testtool/login.php @@ -40,8 +40,7 @@ if (!$db = new basis_db()) die('Fehler beim Oeffnen der Datenbankverbindung'); // Start session -session_start(); - +require_once './session_init.php'; // Logout (triggered by logout button in menu.php) if (isset($_GET['logout']) && $_GET['logout'] == true) { @@ -173,6 +172,12 @@ if (isset($_REQUEST['prestudent'])) else $reload_menu = true; } + + if ($rt->externe_ueberwachung && defined('TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED') && TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED) + { + $_SESSION['externe_ueberwachung'] = true; + $_SESSION['externe_ueberwachung_verified'] = false; + } } $pruefling = new pruefling(); @@ -339,6 +344,8 @@ if ((isset($_SESSION['prestudent_id']) && !isset($_SESSION['pruefling_id']) && !isset($_SESSION['confirmation_needed']) && !isset($_SESSION['confirmed_code'])) || (isset($_SESSION['confirmation_needed']) && $_SESSION['confirmation_needed'] === true && isset($_SESSION['confirmed_code']) && $_SESSION['confirmed_code'] === true && + isset($_SESSION['externe_ueberwachung']) && $_SESSION['externe_ueberwachung'] === true && + isset($_SESSION['externe_ueberwachung_verified']) && $_SESSION['externe_ueberwachung_verified'] === true && isset($_SESSION['prestudent_id']) && !isset($_SESSION['pruefling_id']))) { $pruefling = new pruefling(); @@ -460,7 +467,13 @@ if (isset($_POST['save']) && isset($_SESSION['prestudent_id'])) top.location.href = 'resetconnection.php';"; + exit; +} +else if (isset($_SESSION['confirmation_needed']) && $_SESSION['confirmation_needed'] === true && isset($_SESSION['confirmed_code']) && $_SESSION['confirmed_code'] === false) { echo ' @@ -718,7 +731,7 @@ else // LOGIN Site (vor Login) echo ''; echo '
@@ -728,6 +741,12 @@ else // LOGIN Site (vor Login) '.$p->t('testtool/confirmationText').'

+ + '.$p->t('testtool/dsgvoConfirmText').' +

+ + '.$p->t('testtool/procotoringConfirmText').' +

diff --git a/cis/testtool/menu.php b/cis/testtool/menu.php index 7cb6f138d..11e032f0b 100644 --- a/cis/testtool/menu.php +++ b/cis/testtool/menu.php @@ -34,7 +34,7 @@ if (!$db = new basis_db()) die('Fehler beim Oeffnen der Datenbankverbindung'); // Start session -session_start(); +require_once './session_init.php'; // If language is changed by language select menu, reset language and session variables if(isset($_GET['sprache_user']) && !empty($_GET['sprache_user'])) @@ -61,8 +61,12 @@ $p = new phrasen($sprache_user); db_add_param($_SESSION['studiengang_kz'])." LIMIT 1"; @@ -73,7 +77,7 @@ if (isset($_SESSION['pruefling_id'])) // Link zur Startseite echo ' - '.$p->t('testtool/startseite').' + '.$p->t('testtool/startseite').' '; // Link zur Einleitung @@ -83,7 +87,7 @@ if (isset($_SESSION['pruefling_id'])) { echo ' - '.$p->t('testtool/einleitung').' + '.$p->t('testtool/einleitung').' '; } @@ -379,10 +383,13 @@ if (isset($_SESSION['pruefling_id'])) } } + echo ' + - '.$gebietbezeichnung.' + '.$gebietbezeichnung.' + '; @@ -401,7 +408,7 @@ if (isset($_SESSION['pruefling_id'])) // Link zum Logout echo ' - Logout + Logout '; echo ''; @@ -439,5 +446,22 @@ else ''); } }); + + function loadContent(url) + { + if (parent && typeof parent.loadInContent === 'function') + { + parent.loadInContent(url); + return false; + } + + let frame = parent?.frames?.["content"]; + if (frame) + { + frame.location.href = url; + return false; + } + } + diff --git a/cis/testtool/resetconnection.php b/cis/testtool/resetconnection.php new file mode 100644 index 000000000..ab2806a1f --- /dev/null +++ b/cis/testtool/resetconnection.php @@ -0,0 +1,18 @@ +start($_SESSION['prestudent_id'], $_SESSION['reihungstestID'], $_SESSION['sprache']); + $urlSafe = htmlspecialchars($url, ENT_QUOTES); + header("Location: $urlSafe"); + $_SESSION['externe_ueberwachung_verified'] = true; +} \ No newline at end of file diff --git a/cis/testtool/session_init.php b/cis/testtool/session_init.php new file mode 100644 index 000000000..fd7f0b5f3 --- /dev/null +++ b/cis/testtool/session_init.php @@ -0,0 +1,11 @@ +=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4.8 <=9" + }, + "suggest": { + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "support": { + "issues": "https://github.com/firebase/php-jwt/issues", + "source": "https://github.com/firebase/php-jwt/tree/v6.0.0" + }, + "time": "2022-01-24T15:18:34+00:00" + }, { "name": "fortawesome/font-awesome4", "version": "4.7.0", diff --git a/config/cis.config-default.inc.php b/config/cis.config-default.inc.php index 9985a90d4..5dba1cea8 100644 --- a/config/cis.config-default.inc.php +++ b/config/cis.config-default.inc.php @@ -301,4 +301,17 @@ define ('DEFAULT_ECHTER_DIENSTVERTRAG',[103,111]); // Weiterleiten zu CIS neu (wenn Rechte vorhanden) define('CIS_REDIRECT_TO_CIS4', false); + +//Externe Ueberwachung +define('EXTERNE_UEBERWACHUNG_PROTOCOL_URL', 'https://example.com'); +define('EXTERNE_UEBERWACHUNG_SECRET_KEY', null); +define('EXTERNE_UEBERWACHUNG_INTEGRATION_NAME', 'example'); +define('EXTERNE_UEBERWACHUNG_SESSION_URL', 'https://example.com'); +define('EXTERNE_UEBERWACHUNG_TRIAL_TEST', false); +define('EXTERNE_UEBERWACHUNG_EXAM_PARAMS', []); +define('EXTERNE_UEBERWACHUNG_EXAM_RULES', []); +define('EXTERNE_UEBERWACHUNG_EXAM_SCORE', []); +define('EXTERNE_UEBERWACHUNG_EXAM_WARNINGS', []); + + ?> diff --git a/config/global.config-default.inc.php b/config/global.config-default.inc.php index 37bedbdcb..c43cb38d1 100644 --- a/config/global.config-default.inc.php +++ b/config/global.config-default.inc.php @@ -28,11 +28,15 @@ define('CIS_LEHRVERANSTALTUNG_LEHRFACH_ANZEIGEN',false); define('CIS_LEHRVERANSTALTUNG_GESAMTNOTE_ANZEIGEN', true); define('CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN', true); define('CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN', true); +define('CIS_LEHRVERANSTALTUNG_EVALUIERUNG_ANZEIGEN', true); // Wenn gesetzt, werden die Digitale Anwesenheit-Icons nur fuer diese Studiengaenge angezeigt, sonst für alle // define('CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN_STG', serialize(array('257'))); // define('CIS_LEHRVERANSTALTUNG_ANWESENHEIT_ANZEIGEN_LVA', serialize(array('39455','39481','39480','41906','41905','41904','39459','39512','39454','39482','42230','42231','39458','41921','41922','39457','42896'))); +// Wenn gesetzt, werden die LV-Evaluierung-Icons nur für diese Studiengaenge angezeigt, sonst alle +define('CIS_EVALUIERUNG_ANZEIGEN_STG', serialize((array('335', '585', '914', '298')))); // BIW, MAI, BUB, MIO + // Im CIS Menue Links bei Modulen anzeigen wenn Lehrauftrag define('CIS_LEHRVERANSTALTUNG_MODULE_LINK',true); @@ -364,4 +368,7 @@ define('SANCHO_MAIL_FOOTER_IMG', 'sancho_footer_DEFAULT.jpg'); // Gibt an, ob in der StudVW der Status vorgerueckt werden kann define('STATUS_VORRUECKEN_ANZEIGEN', true); +//externe Ueberwachung im Testtool erlauben +define('TESTTOOL_EXTERNE_UEBERWACHUNG_ALLOWED', false); + ?> diff --git a/include/anwesenheit.class.php b/include/anwesenheit.class.php index 2b8389c79..f601d6b95 100644 --- a/include/anwesenheit.class.php +++ b/include/anwesenheit.class.php @@ -479,91 +479,181 @@ class anwesenheit extends basis_db */ public function loadAnwesenheitStudiensemester($studiensemester_kurzbz, $student_uid=null, $lehrveranstaltung_id=null) { - $qry = "SELECT - lehrveranstaltung_id, vorname, nachname, wahlname, student_uid as uid, bezeichnung, - gesamt as gesamtstunden, anwesend, nichtanwesend, trunc(100-(nichtanwesend/gesamt)*100,2) as prozent - FROM - ( - SELECT - vorname, nachname, wahlname, lehrveranstaltung_id, bezeichnung, gruppe, student_uid, - count(stundenplan_id) as gesamt, - case when anwesend.summe is null then 0 else anwesend.summe end as anwesend, - case when nichtanwesend.summe is null then 0 else nichtanwesend.summe end as nichtanwesend + $qry = "SELECT + lehrveranstaltung_id, + vorname, + nachname, + wahlname, + student_uid AS uid, + bezeichnung, + gesamt AS gesamtstunden, + anwesend, + nichtanwesend, + trunc(100-(nichtanwesend/gesamt)*100,2) AS prozent + + FROM( + SELECT + vorname, + nachname, + wahlname, + lehrveranstaltung_id, + bezeichnung, + student_uid, + COUNT(stundenplan_id) AS gesamt, + CASE WHEN anwesend.summe IS NULL THEN 0 ELSE anwesend.summe END AS anwesend, + CASE WHEN nichtanwesend.summe IS NULL THEN 0 ELSE nichtanwesend.summe END AS nichtanwesend + FROM ( - SELECT - sum(stundenplan_id) as stundenplan_id, datum, stunde, lehrveranstaltung_id, - bezeichnung, studiensemester_kurzbz, studiengang_kz, - TRIM( - CASE WHEN stp.gruppe_kurzbz is not null then stp.gruppe_kurzbz - else stp.semester||(case when verband is null then '' else stp.verband end)||(case when stp.gruppe is null then '' else stp.gruppe end) end) as gruppe + SELECT + SUM(stundenplan_id) AS stundenplan_id, + datum, + stunde, + lehrveranstaltung_id, + bezeichnung, + studiensemester_kurzbz, + studiengang_kz + FROM lehre.tbl_lehrveranstaltung lv - JOIN lehre.tbl_lehreinheit le using (lehrveranstaltung_id) - JOIN lehre.tbl_stundenplan stp using (lehreinheit_id,studiengang_kz) + JOIN + lehre.tbl_lehreinheit le USING (lehrveranstaltung_id) + JOIN + lehre.tbl_stundenplan stp USING (lehreinheit_id,studiengang_kz) + WHERE studiensemester_kurzbz = ".$this->db_add_param($studiensemester_kurzbz)." - AND (titel not like '%Nebenprüfung%' OR titel is null) - - group by datum, stunde, lehrveranstaltung_id, bezeichnung, studiensemester_kurzbz, studiengang_kz, stp.gruppe_kurzbz, stp.semester, stp.verband, stp.gruppe + AND (titel NOT LIKE '%Nebenprüfung%' OR titel IS NULL) + + GROUP BY + datum, + stunde, + lehrveranstaltung_id, + bezeichnung, + studiensemester_kurzbz, + studiengang_kz, + stp.gruppe_kurzbz, + stp.semester, + stp.verband, + stp.gruppe )x JOIN ( - SELECT semester::text as gruppe, public.tbl_studentlehrverband.studiensemester_kurzbz, student_uid, studiengang_kz - FROM - public.tbl_studentlehrverband - WHERE studiensemester_kurzbz = ".$this->db_add_param($studiensemester_kurzbz)." - - UNION - - SELECT semester||verband as gruppe, public.tbl_studentlehrverband.studiensemester_kurzbz, student_uid, studiengang_kz - FROM - public.tbl_studentlehrverband - WHERE - studiensemester_kurzbz = ".$this->db_add_param($studiensemester_kurzbz)." - - UNION - - SELECT semester||verband||gruppe as gruppe, public.tbl_studentlehrverband.studiensemester_kurzbz, student_uid, studiengang_kz - FROM - public.tbl_studentlehrverband - WHERE - studiensemester_kurzbz = ".$this->db_add_param($studiensemester_kurzbz)." - - UNION - - SELECT gruppe_kurzbz as gruppe, public.tbl_benutzergruppe.studiensemester_kurzbz, uid as student_uid, studiengang_kz - FROM - public.tbl_benutzergruppe - JOIN - public.tbl_gruppe using (gruppe_kurzbz) - WHERE studiensemester_kurzbz = ".$this->db_add_param($studiensemester_kurzbz)." - - )a using (gruppe, studiensemester_kurzbz, studiengang_kz) - JOIN public.tbl_benutzer b on b.uid = student_uid - JOIN public.tbl_person p using(person_id) - LEFT JOIN( SELECT - lehrveranstaltung_id, studiensemester_kurzbz, uid as student_uid, sum(einheiten) as summe - FROM - campus.tbl_anwesenheit a - JOIN lehre.tbl_lehreinheit le using (lehreinheit_id) - JOIN lehre.tbl_lehrveranstaltung lv using (lehrveranstaltung_id) - WHERE - anwesend = true AND studiensemester_kurzbz = ".$this->db_add_param($studiensemester_kurzbz)." + le.lehrveranstaltung_id, + slv.student_uid, + le.studiensemester_kurzbz, + st.prestudent_id + + FROM + public.tbl_studentlehrverband slv + JOIN + lehre.tbl_lehreinheitgruppe leg + ON slv.studiengang_kz = leg.studiengang_kz + AND slv.semester = leg.semester + AND ( + NULLIF(btrim(leg.verband::text), '') IS NULL + OR NULLIF(btrim(slv.verband::text), '') = NULLIF(btrim(leg.verband::text), '') + ) + AND ( + NULLIF(btrim(leg.gruppe::text), '') IS NULL + OR NULLIF(btrim(slv.gruppe::text), '') = NULLIF(btrim(leg.gruppe::text), '') + ) + JOIN + lehre.tbl_lehreinheit le USING (lehreinheit_id, studiensemester_kurzbz) + JOIN + public.tbl_student st USING(student_uid) + + WHERE + leg.gruppe_kurzbz IS NULL + AND le.studiensemester_kurzbz = ".$this->db_add_param($studiensemester_kurzbz)." + GROUP BY - lehrveranstaltung_id, bezeichnung, uid, studiensemester_kurzbz - )anwesend using(lehrveranstaltung_id, student_uid, studiensemester_kurzbz) + le.lehrveranstaltung_id, + slv.student_uid, + le.studiensemester_kurzbz, + st.prestudent_id + + UNION + + SELECT + le.lehrveranstaltung_id, + bg.uid AS student_uid, + bg.studiensemester_kurzbz, + st.prestudent_id + + FROM + public.tbl_benutzergruppe bg + JOIN + lehre.tbl_lehreinheitgruppe leg USING (gruppe_kurzbz) + JOIN + lehre.tbl_lehreinheit le USING(lehreinheit_id, studiensemester_kurzbz) + JOIN + public.tbl_student st ON bg.uid = st.student_uid + + WHERE + bg.studiensemester_kurzbz = ".$this->db_add_param($studiensemester_kurzbz)." + + GROUP BY + le.lehrveranstaltung_id, + bg.uid, + bg.studiensemester_kurzbz, + st.prestudent_id + + )a USING (lehrveranstaltung_id, studiensemester_kurzbz) + JOIN + public.tbl_benutzer b on b.uid = student_uid + JOIN + public.tbl_person p using(person_id) LEFT JOIN( - SELECT lehrveranstaltung_id, studiensemester_kurzbz, uid as student_uid, sum(einheiten) as summe + SELECT + lehrveranstaltung_id, + studiensemester_kurzbz, + uid AS student_uid, + SUM(einheiten) AS summe + FROM campus.tbl_anwesenheit a - JOIN lehre.tbl_lehreinheit le using (lehreinheit_id) - JOIN lehre.tbl_lehrveranstaltung lv using (lehrveranstaltung_id) + JOIN + lehre.tbl_lehreinheit le USING(lehreinheit_id) + JOIN + lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id) + WHERE - anwesend = false AND studiensemester_kurzbz = ".$this->db_add_param($studiensemester_kurzbz)." + anwesend = true + AND studiensemester_kurzbz = ".$this->db_add_param($studiensemester_kurzbz)." + GROUP BY - lehrveranstaltung_id, bezeichnung, uid, studiensemester_kurzbz - )nichtanwesend using(lehrveranstaltung_id, student_uid, studiensemester_kurzbz) + lehrveranstaltung_id, + bezeichnung, + uid, + studiensemester_kurzbz + + )anwesend USING(lehrveranstaltung_id, student_uid, studiensemester_kurzbz) + LEFT JOIN( + SELECT + lehrveranstaltung_id, + studiensemester_kurzbz, + uid AS student_uid, + SUM(einheiten) AS summe + + FROM + campus.tbl_anwesenheit a + JOIN + lehre.tbl_lehreinheit le USING (lehreinheit_id) + JOIN + lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id) + + WHERE + anwesend = false + AND studiensemester_kurzbz = ".$this->db_add_param($studiensemester_kurzbz)." + + GROUP BY + lehrveranstaltung_id, + bezeichnung, + uid, + studiensemester_kurzbz + )nichtanwesend USING(lehrveranstaltung_id, student_uid, studiensemester_kurzbz) + WHERE lehrveranstaltung_id > 0 "; @@ -573,8 +663,15 @@ class anwesenheit extends basis_db if(!is_null($lehrveranstaltung_id)) $qry.=" AND lehrveranstaltung_id=".$this->db_add_param($lehrveranstaltung_id); - $qry.="group by - vorname, nachname, wahlname, lehrveranstaltung_id, bezeichnung, gruppe, student_uid, anwesend.summe, nichtanwesend.summe + $qry.=" GROUP BY + vorname, + nachname, + wahlname, + lehrveranstaltung_id, + bezeichnung, + student_uid, + anwesend.summe, + nichtanwesend.summe )m"; if($lehrveranstaltung_id != '') diff --git a/include/externe_ueberwachung.class.php b/include/externe_ueberwachung.class.php new file mode 100644 index 000000000..17343669b --- /dev/null +++ b/include/externe_ueberwachung.class.php @@ -0,0 +1,221 @@ +getSessionByPrestudent($prestudent_id); + return $this->getSessionStatus($session_id); + } + public function start($prestudent_id, $reihungstest_id, $sprache) + { + $session_id = $this->getSessionByPrestudent($prestudent_id); + + if (!$session_id) + { + $session_id = $this->createSession($prestudent_id); + } + else + { + $status = $this->getSessionStatus($session_id); + + if (in_array($status, array('late_to_start', 'finished'))) + { + $session_id = $this->createSession($prestudent_id); + } + } + + $payload = $this->getPayload($session_id, $prestudent_id, $reihungstest_id, $sprache); + return $this->getStartUrl($payload); + } + + + private function createSession($prestudent_id) + { + if (is_null($prestudent_id)) + { + $this->errormsg = 'Falsche Parameterübergabe'; + return false; + } + + $uuid = $this->genereateUUID(); + + $qry = "INSERT INTO testtool.tbl_externe_ueberwachung (prestudent_id, session_id) + VALUES (". + $this->db_add_param($prestudent_id).",". + $this->db_add_param($uuid).")"; + + if($this->db_query($qry)) + { + return $uuid; + } + else + { + $this->errormsg = 'Fehler beim Speichern der Antwort'; + return false; + } + } + public function getSessionByPrestudent($prestudent_id) + { + if (is_null($prestudent_id)) + { + $this->errormsg = 'Falsche Parameterübergabe'; + return false; + } + + $qry = "SELECT session_id + FROM testtool.tbl_externe_ueberwachung + WHERE prestudent_id = ".$this->db_add_param($prestudent_id, FHC_INTEGER) . " + ORDER BY insertamum DESC + LIMIT 1"; + + if($result = $this->db_query($qry)) + { + if ($row = $this->db_fetch_object($result)) + { + return $row->session_id; + } + else + { + $this->errormsg = 'Daten konnten nicht geladen werden'; + return false; + } + } + else + { + $this->errormsg = 'Fehler bei einer Abfrage'; + return false; + } + } + + public function getSessionStatus($session_id) + { + $payload = $this->getSessionPayload($session_id); + $jwt = $this->createToken($payload); + + $url = $this->getSessionUrl($session_id); + + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + "Authorization: JWT {$jwt}", + "Content-Type: application/json", + ]); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); + + $response = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + + curl_close($ch); + + $data = json_decode($response, true); + return isset($data['status']) ? $data['status'] : false; + } + + private function getSessionPayload($session_id) + { + return [ + "session_id" => $session_id, + "iat" => time(), + "exp" => time() + 120, + ]; + } + + private function getPayload($session_id, $prestudent_id, $reihungstest_id, $sprache) + { + $prestudent = new prestudent($prestudent_id); + $person = new Person($prestudent->person_id); + + $reihungstest = new Reihungstest($reihungstest_id); + + $datetime = new DateTime(); + $today = $datetime->format('Y-m-d'); + + $payload = [ + "userId" => $prestudent_id, + "lastName" => $person->nachname, + "firstName" => $person->vorname, + "language" => $sprache === 'German' ? 'de' : 'en', + "accountName" => "technikum_wien", + "accountId" => "technikum_wien", + "examId" => $reihungstest_id . '_' . $today, + "examName" => !is_null(trim($reihungstest->anmerkung)) ? ($reihungstest->anmerkung . '_' . $today) : ($reihungstest_id . '_' . $today), + "duration" => 1440, + "schedule" => false, + "trial" => EXTERNE_UEBERWACHUNG_TRIAL_TEST, + "proctoring" => "offline", + "startDate" => $reihungstest->datum . 'T00:00:00Z', + "endDate" => $reihungstest->datum . 'T23:59:59Z', + "sessionId" => $session_id, + "sessionUrl" => EXTERNE_UEBERWACHUNG_SESSION_URL + ]; + + if (defined('EXTERNE_UEBERWACHUNG_EXAM_PARAMS')) + { + $payload = array_merge($payload, EXTERNE_UEBERWACHUNG_EXAM_PARAMS); + } + + if (defined('EXTERNE_UEBERWACHUNG_EXAM_WARNINGS')) + { + $payload['visibleWarnings'] = EXTERNE_UEBERWACHUNG_EXAM_WARNINGS; + } + + if (defined('EXTERNE_UEBERWACHUNG_EXAM_RULES')) + { + $payload['rules'] = EXTERNE_UEBERWACHUNG_EXAM_RULES; + } + + if (defined('EXTERNE_UEBERWACHUNG_EXAM_SCORE')) + { + $payload['scoreConfig'] = EXTERNE_UEBERWACHUNG_EXAM_SCORE; + } + + return $payload; + } + + private function getSessionUrl($session_id) + { + return EXTERNE_UEBERWACHUNG_PROTOCOL_URL . "/api/v2/integration/simple/". EXTERNE_UEBERWACHUNG_INTEGRATION_NAME . "/sessions/". urlencode($session_id) ."/status/"; + } + + private function getStartUrl($payload) + { + $token = $this->createToken($payload); + $query = http_build_query(['token' => $token]); + + return EXTERNE_UEBERWACHUNG_PROTOCOL_URL . '/integration/simple/'. EXTERNE_UEBERWACHUNG_INTEGRATION_NAME .'/start?' . $query; + } + + private function createToken($payload) + { + return JWT::encode($payload, EXTERNE_UEBERWACHUNG_SECRET_KEY, 'HS256'); + } + + private function genereateUUID() + { + $data = openssl_random_pseudo_bytes(16); + + $data[6] = chr(ord($data[6]) & 0x0f | 0x40); + $data[8] = chr(ord($data[8]) & 0x3f | 0x80); + + return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)); + } +} + +?> + + + diff --git a/include/lehrveranstaltung.class.php b/include/lehrveranstaltung.class.php index 26f846f8e..cc89556c7 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; diff --git a/include/reihungstest.class.php b/include/reihungstest.class.php index df4134ebf..94d064c25 100644 --- a/include/reihungstest.class.php +++ b/include/reihungstest.class.php @@ -63,6 +63,7 @@ class reihungstest extends basis_db public $zugangs_ueberpruefung = false; //boolean public $zugangscode; //smallint + public $externe_ueberwachung = false; //boolean /** @@ -119,6 +120,7 @@ class reihungstest extends basis_db $this->aufnahmegruppe_kurzbz = $row->aufnahmegruppe_kurzbz; $this->zugangs_ueberpruefung = $this->db_parse_bool($row->zugangs_ueberpruefung); $this->zugangscode = $row->zugangscode; + $this->externe_ueberwachung = $this->db_parse_bool($row->externe_ueberwachung); return true; } @@ -234,7 +236,7 @@ class reihungstest extends basis_db $qry = 'BEGIN; INSERT INTO public.tbl_reihungstest (studiengang_kz, ort_kurzbz, anmerkung, datum, uhrzeit, insertamum, insertvon, updateamum, updatevon, max_teilnehmer, oeffentlich, freigeschaltet, - studiensemester_kurzbz, stufe, anmeldefrist, aufnahmegruppe_kurzbz, zugangs_ueberpruefung, zugangscode) VALUES('. + studiensemester_kurzbz, stufe, anmeldefrist, aufnahmegruppe_kurzbz, zugangs_ueberpruefung, zugangscode, externe_ueberwachung) VALUES('. $this->db_add_param($this->studiengang_kz, FHC_INTEGER).', '. $this->db_add_param($this->ort_kurzbz).', '. $this->db_add_param($this->anmerkung).', '. @@ -250,7 +252,8 @@ class reihungstest extends basis_db $this->db_add_param($this->anmeldefrist).','. $this->db_add_param($this->aufnahmegruppe_kurzbz). ',' . $this->db_add_param($this->zugangs_ueberpruefung, FHC_BOOLEAN).','. - $this->db_add_param($this->zugangscode) . ');'; + $this->db_add_param($this->zugangscode) . ','. + $this->db_add_param($this->externe_ueberwachung, FHC_BOOLEAN) . ');'; } else { @@ -270,7 +273,8 @@ class reihungstest extends basis_db 'anmeldefrist='.$this->db_add_param($this->anmeldefrist).', '. 'aufnahmegruppe_kurzbz='.$this->db_add_param($this->aufnahmegruppe_kurzbz).', '. 'zugangs_ueberpruefung='.$this->db_add_param($this->zugangs_ueberpruefung, FHC_BOOLEAN).', '. - 'zugangscode='.$this->db_add_param($this->zugangscode).' '. + 'zugangscode='.$this->db_add_param($this->zugangscode).', '. + 'externe_ueberwachung='.$this->db_add_param($this->externe_ueberwachung, FHC_BOOLEAN).' '. 'WHERE reihungstest_id='.$this->db_add_param($this->reihungstest_id, FHC_INTEGER, false).';'; } diff --git a/include/tw/cis_menu_lv.inc.php b/include/tw/cis_menu_lv.inc.php index 29ba54724..03ce016ca 100644 --- a/include/tw/cis_menu_lv.inc.php +++ b/include/tw/cis_menu_lv.inc.php @@ -500,6 +500,27 @@ if((!defined('CIS_LEHRVERANSTALTUNG_ANRECHNUNG_ANZEIGEN') || CIS_LEHRVERANSTALTU ); } +// LV-Evaluierung NEU +if(defined('CIS_LEHRVERANSTALTUNG_EVALUIERUNG_ANZEIGEN') + && CIS_LEHRVERANSTALTUNG_EVALUIERUNG_ANZEIGEN + && $angemeldet + && (!defined('CIS_EVALUIERUNG_ANZEIGEN_STG') || in_array($lv->studiengang_kz, unserialize(CIS_EVALUIERUNG_ANZEIGEN_STG))) + && ($rechte->isBerechtigt('extension/lvevaluierung_init'))) +{ + $text='(Pilotphase)'; + + $link= APP_ROOT. 'index.ci.php/extensions/FHC-Core-Evaluierung/Initiierung?lehrveranstaltung_id='. urlencode($lv->lehrveranstaltung_id).'&studiensemester_kurzbz='.urlencode($angezeigtes_stsem); + + $menu[]=array + ( + 'id'=>'extension_lvevaluierung_menu_initiierung', + 'position'=>'140', + 'name'=>$p->t('lvevaluierung/lvevaluierung'). ' - '. strtoupper($p->t('global/neu')), + 'icon'=>'../../../skin/images/button_lvevaluierung.png', + 'link'=> $link, + 'text'=>$text + ); +} //************* Menuepunkte anzeigen **************** diff --git a/locale/de-AT/testtool.php b/locale/de-AT/testtool.php index 6977704cc..33c46b0a7 100644 --- a/locale/de-AT/testtool.php +++ b/locale/de-AT/testtool.php @@ -53,6 +53,10 @@ $this->phrasen['testtool/fuerFolgendeStgAngemeldet']='Für folgende Studiengäng $this->phrasen['testtool/invalideGebiete']='Ein oder mehrere Fragengebiet/e inkorrekt!
Bitte melden Sie dies der Betreuungsperson.'; $this->phrasen['testtool/confirmationText']='Ich bestätige, den Online-Reihungstest persönlich, selbständig, ohne Hilfe einer zusätzlichen Person und ohne Hilfsmittel zu absolvieren.
I confirm that I will complete the online placement test personally, independently, without the help of an additional person and without any aids.
'; +$this->phrasen['testtool/dsgvoConfirmText']='Ich habe die Datenschutzerklärung gelesen.
+I have read the privacy policy.
'; +$this->phrasen['testtool/procotoringConfirmText']='Ich stimme der digitalen Beaufsichtigung beim Online-Reihungstest (Proctoring) zu.
+I agree to the digital supervision of the online placement test (proctoring).
'; $this->phrasen['testtool/loginNoetig']='Bitte beachten Sie, dass der Reihungstest erst unmittelbar vor Ihrem Reihungstesttermin von uns aktiviert wird.
Please note that the test will be activated by us immediately before your placement test date.'; $this->phrasen['testtool/start']='Reihungstest jetzt starten'; diff --git a/public/.htaccess_sample b/public/.htaccess_sample new file mode 100644 index 000000000..e3f3485f6 --- /dev/null +++ b/public/.htaccess_sample @@ -0,0 +1,9 @@ + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule ^[0-9]{10}/(.*)$ $1 [L] + RewriteCond %{REQUEST_URI} ^(.*?)/public/index.ci.php/ + RewriteRule ^index.ci.php/(.*)$ %1/index.ci.php/$1 [R=303] + + diff --git a/public/css/Cis4/Cis.css b/public/css/Cis4/Cis.css index 2bb467048..3056d36b6 100644 --- a/public/css/Cis4/Cis.css +++ b/public/css/Cis4/Cis.css @@ -407,7 +407,6 @@ html { background-color: var(--fhc-background); border-color: var(--fhc-border); padding: var(--fhc-cis-main-py) var(--fhc-cis-main-px); - min-width: 0; /* fix flex-grow with tabulator exceeding width */ } #cis-main .fa-arrow-up-right-from-square { @@ -856,3 +855,9 @@ html { background-color: var(--fhc-secondary); } + +.bordered-modal { + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 0.5rem; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25); +} \ No newline at end of file diff --git a/public/css/components/abgabetool/abgabe.css b/public/css/components/abgabetool/abgabe.css new file mode 100644 index 000000000..d70481805 --- /dev/null +++ b/public/css/components/abgabetool/abgabe.css @@ -0,0 +1,308 @@ +/* Base Header */ +.verpasst-header { + background-color: var(--fhc-red-70); + font-weight: 600; + border-radius: 6px; + padding: 0px 0px 0px 34px; + transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease; + box-shadow: 0 1px 2px rgba(0,0,0,0.08); +} + +/* Hover State */ +.verpasst-header:hover { + background-color: var(--fhc-red-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Active / Expanded State */ +.p-accordion-tab-active > .verpasst-header { + background-color: var(--fhc-red-50); + box-shadow: 0 2px 8px rgba(0,0,0,0.2); +} + +/* Hover State Active*/ +.p-accordion-tab-active > .verpasst-header:hover { + background-color: var(--fhc-red-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Base Header */ +.abzugeben-header { + background-color: var(--fhc-yellow-70); + font-weight: 600; + border-radius: 6px; + padding: 0px 0px 0px 34px; + transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease; + box-shadow: 0 1px 2px rgba(0,0,0,0.08); +} + +/* Hover State */ +.abzugeben-header:hover { + background-color: var(--fhc-yellow-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Active / Expanded State */ +.p-accordion-tab-active > .abzugeben-header { + background-color: var(--fhc-yellow-50); + box-shadow: 0 2px 8px rgba(0,0,0,0.2); +} + +/* Hover State Active*/ +.p-accordion-tab-active > .abzugeben-header:hover { + background-color: var(--fhc-yellow-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Base Header */ +.beurteilungerforderlich-header { + background-color: var(--fhc-orange-70); + font-weight: 600; + border-radius: 6px; + padding: 0px 0px 0px 34px; + transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease; + box-shadow: 0 1px 2px rgba(0,0,0,0.08); +} + + +/* Hover State */ +.beurteilungerforderlich-header:hover { + background-color: var(--fhc-orange-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Active / Expanded State */ +.p-accordion-tab-active > .beurteilungerforderlich-header { + background-color: var(--fhc-orange-50); + box-shadow: 0 2px 8px rgba(0,0,0,0.2); +} + +/* Hover State Active*/ +.p-accordion-tab-active > .beurteilungerforderlich-header:hover { + background-color: var(--fhc-orange-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Base Header */ +.verspaetet-header { + background-color: var(--fhc-pink-40); + font-weight: 600; + border-radius: 6px; + padding: 0px 0px 0px 34px; + transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease; + box-shadow: 0 1px 2px rgba(0,0,0,0.08); +} + +/* Hover State */ +.verspaetet-header:hover { + background-color: var(--fhc-pink-20); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Active / Expanded State */ +.p-accordion-tab-active > .verspaetet-header { + background-color: var(--fhc-pink-30); + box-shadow: 0 2px 8px rgba(0,0,0,0.2); +} + +/* Hover State Active*/ +.p-accordion-tab-active > .verspaetet-header:hover { + background-color: var(--fhc-pink-20); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Base Header */ +.abgegeben-header { + background-color: var(--fhc-green-70); + font-weight: 600; + border-radius: 6px; + padding: 0px 0px 0px 34px; + transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease; + box-shadow: 0 1px 2px rgba(0,0,0,0.08); +} + +/* Hover State */ +.abgegeben-header:hover { + background-color: var(--fhc-green-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Active / Expanded State */ +.p-accordion-tab-active > .abgegeben-header { + background-color: var(--fhc-green-50); + box-shadow: 0 2px 8px rgba(0,0,0,0.2); +} + +/* Hover State Active*/ +.p-accordion-tab-active > .abgegeben-header:hover { + background-color: var(--fhc-green-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + + +/* Base Header */ +.bestanden-header { + background-color: var(--fhc-green-70); + font-weight: 600; + border-radius: 6px; + padding: 0px 0px 0px 34px; + transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease; + box-shadow: 0 1px 2px rgba(0,0,0,0.08); +} + +/* Hover State */ +.bestanden-header:hover { + background-color: var(--fhc-green-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Active / Expanded State */ +.p-accordion-tab-active > .bestanden-header { + background-color: var(--fhc-green-50); + box-shadow: 0 2px 8px rgba(0,0,0,0.2); +} + +/* Hover State Active*/ +.p-accordion-tab-active > .bestanden-header:hover { + background-color: var(--fhc-green-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + + +/* Base Header */ +.nichtbestanden-header { + background-color: var(--fhc-red-70); + font-weight: 600; + border-radius: 6px; + padding: 0px 0px 0px 34px; + transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease; + box-shadow: 0 1px 2px rgba(0,0,0,0.08); +} + +/* Hover State */ +.nichtbestanden-header:hover { + background-color: var(--fhc-red-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Active / Expanded State */ +.p-accordion-tab-active > .nichtbestanden-header { + background-color: var(--fhc-red-50); + box-shadow: 0 2px 8px rgba(0,0,0,0.2); +} + +/* Hover State Active*/ +.p-accordion-tab-active > .nichtbestanden-header:hover { + background-color: var(--fhc-red-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + + +/* Base Header */ +.erledigt-header { + background-color: var(--fhc-red-70); + font-weight: 600; + border-radius: 6px; + padding: 0px 0px 0px 34px; + transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease; + box-shadow: 0 1px 2px rgba(0,0,0,0.08); +} + +/* Hover State */ +.erledigt-header:hover { + background-color: var(--fhc-red-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Active / Expanded State */ +.p-accordion-tab-active > .erledigt-header { + background-color: var(--fhc-red-50); + box-shadow: 0 2px 8px rgba(0,0,0,0.2); +} + +/* Hover State Active*/ +.p-accordion-tab-active > .erledigt-header:hover { + background-color: var(--fhc-red-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + + +/* Base Header */ +.standard-header { + background-color: var(--fhc-white-70); + font-weight: 600; + border-radius: 6px; + padding: 0px 0px 0px 34px; + transition: background-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease; + box-shadow: 0 1px 2px rgba(0,0,0,0.08); +} + +/* Hover State */ +.standard-header:hover { + background-color: var(--fhc-white-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +/* Active / Expanded State */ +.p-accordion-tab-active > .standard-header { + background-color: var(--fhc-white-50); + box-shadow: 0 2px 8px rgba(0,0,0,0.2); +} + +/* Hover State Active*/ +.p-accordion-tab-active > .standard-header:hover { + background-color: var(--fhc-white-60); + box-shadow: 0 2px 6px rgba(0,0,0,0.12); +} + +#abgabetoolroot .modal-header{ + background-color: var(--fhc-blue-primary); + color: var(--fhc-white-50); +} + +#abgabetoolroot .modal-header .btn-close{ + filter: invert(1); +} + +#abgabetoolroot .modal-footer { + background-color: var(--fhc-white-20); + +} + +.bordered-modal { + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 0.5rem; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.25); +} + +.bordered-modal .modal-body { + overflow-y: visible; +} + +.p-accordion .p-accordion-header .p-accordion-header-link { + padding: 12px!important; +} + +/* 1. Stick the Header */ +#abgabetable .tabulator-header .tabulator-col.sticky-col { + position: sticky; + left: 0; + z-index: 10; /* Must be higher than other headers */ + background-color: #fff; /* Opaque background is required */ + border-right: 2px solid #ddd; /* Optional: Separator line */ +} + +/* 2. Stick the Data Cells */ +#abgabetable .tabulator-tableholder .tabulator-row .tabulator-cell.sticky-col { + position: sticky; + left: 0; + z-index: 10; /* Ensure it floats above other cells */ + background-color: #fff; /* Match your row background color */ + border-right: 2px solid #ddd; /* Optional: Separator line */ +} + +/* 3. Fix for Hover Effects (Optional) */ +/* If you use hover rows, you need to ensure the sticky cell matches the hover color */ +#abgabetable .tabulator-row:hover .tabulator-cell.sticky-col { + background-color: #ccc; /* Match your existing hover color */ +} \ No newline at end of file diff --git a/public/css/theme/default.css b/public/css/theme/default.css index a0f366174..a4d197f07 100644 --- a/public/css/theme/default.css +++ b/public/css/theme/default.css @@ -38,15 +38,104 @@ --fhc-blue-primary: #006095; --fhc-blue-primary-highlight: #0086CB; - --fhc-red-10: #842029; - --fhc-red-20: #800000; + /* --- Green --- */ + --fhc-green-5: rgb(240, 250, 240); + --fhc-green-10: rgb(220, 245, 220); + --fhc-green-20: rgb(190, 235, 190); + --fhc-green-30: rgb(150, 220, 150); + --fhc-green-40: rgb(110, 200, 110); + --fhc-green-50: rgb(70, 170, 70); + --fhc-green-60: rgb(50, 145, 50); + --fhc-green-70: rgb(35, 120, 35); + --fhc-green-80: rgb(25, 95, 25); + --fhc-green-90: rgb(15, 70, 15); - --fhc-green-10: #008000; + /* --- Red --- */ + --fhc-red-5: rgb(255, 245, 246); + --fhc-red-10: rgb(255, 225, 228); + --fhc-red-20: rgb(250, 190, 195); + --fhc-red-30: rgb(240, 150, 160); + --fhc-red-40: rgb(225, 110, 120); + --fhc-red-50: rgb(200, 70, 85); + --fhc-red-60: rgb(170, 50, 65); + --fhc-red-70: rgb(140, 35, 50); + --fhc-red-80: rgb(110, 20, 35); + --fhc-red-90: rgb(85, 10, 25); + /* --- Yellow --- */ + --fhc-yellow-5: rgb(255, 255, 240); + --fhc-yellow-10: rgb(255, 250, 210); + --fhc-yellow-20: rgb(255, 240, 160); + --fhc-yellow-30: rgb(255, 225, 100); + --fhc-yellow-40: rgb(250, 210, 50); + --fhc-yellow-50: rgb(240, 190, 0); + --fhc-yellow-60: rgb(220, 165, 0); + --fhc-yellow-70: rgb(190, 135, 0); + --fhc-yellow-80: rgb(160, 105, 0); + --fhc-yellow-90: rgb(120, 75, 0); + + /* --- Pink --- */ + --fhc-pink-5: rgb(255, 245, 250); + --fhc-pink-10: rgb(255, 225, 235); + --fhc-pink-20: rgb(250, 195, 215); + --fhc-pink-30: rgb(245, 160, 190); + --fhc-pink-40: rgb(235, 120, 160); + --fhc-pink-50: rgb(220, 80, 130); + --fhc-pink-60: rgb(190, 60, 110); + --fhc-pink-70: rgb(160, 40, 90); + --fhc-pink-80: rgb(130, 25, 70); + --fhc-pink-90: rgb(100, 15, 50); + + /* --- Orange --- */ + --fhc-orange-5: rgb(255, 250, 240); + --fhc-orange-10: rgb(255, 235, 200); + --fhc-orange-20: rgb(255, 210, 140); + --fhc-orange-30: rgb(255, 185, 80); + --fhc-orange-40: rgb(255, 155, 40); + --fhc-orange-50: rgb(255, 128, 0); + --fhc-orange-60: rgb(230, 110, 0); + --fhc-orange-70: rgb(200, 90, 0); + --fhc-orange-80: rgb(170, 70, 0); + --fhc-orange-90: rgb(130, 50, 0); + --fhc-beige-10: rgba(245, 233, 215, 0.5); --fhc-beige-20: rgba(172, 153, 125, 0.5); + /* --- Purple --- */ + --fhc-purple-5: rgb(250, 245, 255); + --fhc-purple-10: rgb(240, 230, 255); + --fhc-purple-20: rgb(220, 200, 250); + --fhc-purple-30: rgb(190, 160, 245); + --fhc-purple-40: rgb(160, 120, 235); + --fhc-purple-50: rgb(130, 80, 220); + --fhc-purple-60: rgb(110, 60, 190); + --fhc-purple-70: rgb(90, 40, 160); + --fhc-purple-80: rgb(70, 25, 130); + --fhc-purple-90: rgb(50, 15, 100); + /* --- Teal --- */ + --fhc-teal-5: rgb(240, 252, 252); + --fhc-teal-10: rgb(220, 245, 245); + --fhc-teal-20: rgb(180, 235, 235); + --fhc-teal-30: rgb(130, 220, 220); + --fhc-teal-40: rgb(80, 200, 200); + --fhc-teal-50: rgb(30, 170, 170); + --fhc-teal-60: rgb(20, 140, 140); + --fhc-teal-70: rgb(15, 115, 115); + --fhc-teal-80: rgb(10, 90, 90); + --fhc-teal-90: rgb(5, 65, 65); + + /* --- Indigo --- */ + --fhc-indigo-5: rgb(245, 247, 255); + --fhc-indigo-10: rgb(230, 235, 255); + --fhc-indigo-20: rgb(200, 210, 250); + --fhc-indigo-30: rgb(160, 175, 245); + --fhc-indigo-40: rgb(120, 140, 235); + --fhc-indigo-50: rgb(80, 100, 220); + --fhc-indigo-60: rgb(60, 80, 190); + --fhc-indigo-70: rgb(45, 60, 160); + --fhc-indigo-80: rgb(30, 40, 130); + --fhc-indigo-90: rgb(20, 25, 100); } diff --git a/public/js/api/factory/abgabe.js b/public/js/api/factory/abgabe.js new file mode 100644 index 000000000..f5659f3a0 --- /dev/null +++ b/public/js/api/factory/abgabe.js @@ -0,0 +1,136 @@ +export default { + getConfig() { + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getConfig' + }; + }, + getConfigStudent() { + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getConfigStudent' + }; + }, + 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" }} + }; + }, + postStudentProjektarbeitZwischenabgabe(formData) { + return { + method: 'post', + url: '/api/frontend/v1/Abgabe/postStudentProjektarbeitZwischenabgabe', + params: formData, + config: {Headers: { "Content-Type": "multipart/form-data" }} + }; + }, + getMitarbeiterProjektarbeiten(all) { + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getMitarbeiterProjektarbeiten', + params: { showall: all } + }; + }, + postProjektarbeitAbgabe(termin) { + + let dateString = termin.datum + if(termin.datum instanceof Date) { + const year = termin.datum.getFullYear(); + const month = String(termin.datum.getMonth() + 1).padStart(2, '0'); + const day = String(termin.datum.getDate()).padStart(2, '0'); + + dateString = `${year}-${month}-${day}` + } + + return { + method: 'post', + url: '/api/frontend/v1/Abgabe/postProjektarbeitAbgabe', + params: { + paabgabe_id: termin.paabgabe_id, + paabgabetyp_kurzbz: termin.bezeichnung.paabgabetyp_kurzbz, + datum: dateString, + note: termin.note_pk, + upload_allowed: !!termin.upload_allowed, + beurteilungsnotiz: termin.beurteilungsnotiz ?? '', + fixtermin: termin.fixtermin, + insertvon: termin.insertvon, + kurzbz: termin.kurzbz, + projektarbeit_id: termin.projektarbeit_id, + betreuer_person_id: termin.betreuer_person_id + } + }; + }, + deleteProjektarbeitAbgabe(paabgabe_id) { + return { + method: 'post', + url: '/api/frontend/v1/Abgabe/deleteProjektarbeitAbgabe', + params: { paabgabe_id } + }; + }, + postSerientermin(datum, paabgabetyp_kurzbz, bezeichnung, kurzbz, upload_allowed, projektarbeit_ids, fixtermin) { + return { + method: 'post', + url: '/api/frontend/v1/Abgabe/postSerientermin', + params: { datum, paabgabetyp_kurzbz, bezeichnung, kurzbz, upload_allowed, projektarbeit_ids, fixtermin } + }; + }, + 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' + }; + }, + //TODO: SWITCH TO NOTEN API ONCE NOTENTOOL IS IN MASTER TO AVOID DUPLICATE API + getNoten(){ + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getNoten' + }; + }, + getProjektarbeitenForStudiengang(studiengang_kz, benotet = 0) { + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getProjektarbeitenForStudiengang', + params: { studiengang_kz, benotet } + }; + }, + // TODO: this could also very well be generic info api + getStudiengaenge() { + return { + method: 'get', + url: '/api/frontend/v1/Abgabe/getStudiengaenge' + }; + }, + postStudentProjektarbeitZusatzdaten(formData) { + return { + method: 'post', + url: '/api/frontend/v1/Abgabe/postStudentProjektarbeitZusatzdaten', + params: formData, + config: {Headers: { "Content-Type": "multipart/form-data" }} + }; + } +}; \ No newline at end of file diff --git a/public/js/api/factory/studiengang.js b/public/js/api/factory/studiengang.js index 6d5ae15aa..12322cb3a 100644 --- a/public/js/api/factory/studiengang.js +++ b/public/js/api/factory/studiengang.js @@ -16,17 +16,10 @@ */ export default { - studiengangInformation() { + getAllStudiensemesterAndAktOrNext() { return { method: 'get', - url: '/api/frontend/v1/Studgang/getStudiengangInfo' + url: '/api/frontend/v1/Studiensemester/getStudiengangInfo' }; }, - getStudiengangByKz(studiengang_kz) { - return { - method: 'get', - url: '/api/frontend/v1/organisation/StudiengangEP/getStudiengangByKz', - params: { studiengang_kz } - }; - } }; \ No newline at end of file diff --git a/public/js/api/factory/studiensemester.js b/public/js/api/factory/studiensemester.js index 367ec9558..7fe4a22d3 100644 --- a/public/js/api/factory/studiensemester.js +++ b/public/js/api/factory/studiensemester.js @@ -1,5 +1,27 @@ -export default { +/** + * Copyright (C) 2025 fhcomplete.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +export default { + getAllStudiensemesterAndAktOrNext() { + return { + method: 'get', + url: '/api/frontend/v1/organisation/Studiensemester/getAllStudiensemesterAndAktOrNext', + }; + }, getAll(order = null, start = null) { return { @@ -8,4 +30,4 @@ export default { params: { order, start } }; } -} \ No newline at end of file +}; \ 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/apps/Abgabetool/Abgabetool.js b/public/js/apps/Abgabetool/Abgabetool.js new file mode 100644 index 000000000..83233ba22 --- /dev/null +++ b/public/js/apps/Abgabetool/Abgabetool.js @@ -0,0 +1,74 @@ +import PluginsPhrasen from '../../plugins/Phrasen.js'; +import AbgabetoolStudent from "../../components/Cis/Abgabetool/AbgabetoolStudent.js"; +import AbgabetoolMitarbeiter from "../../components/Cis/Abgabetool/AbgabetoolMitarbeiter.js"; +import AbgabetoolAssistenz from "../../components/Cis/Abgabetool/AbgabetoolAssistenz.js"; +import DeadlineOverview from "../../components/Cis/Abgabetool/DeadlineOverview.js"; +import {capitalize} from "../../helpers/StringHelpers.js"; + +const app = Vue.createApp({ + name: 'AbgabetoolApp', + components: { + AbgabetoolStudent, + AbgabetoolMitarbeiter, + AbgabetoolAssistenz, + DeadlineOverview + }, + data: function() { + return { + comp: null, + uid: null, + student_uid: null, + stg_kz: null + }; + }, + methods: { + + }, + computed: { + viewData() { + return { uid: this.uid} + }, + student_uid_computed() { + return this.student_uid ?? this.uid + }, + stg_kz_computed() { + return this.stg_kz ?? null + } + }, + created() { + }, + mounted() { + + const root = document.getElementById('abgabetoolroot') + const route = root.getAttribute("route"); + this.comp = route + + const uid = root.getAttribute("uid"); + this.uid = uid + + const stg_kz = root.getAttribute("stg_kz_prop"); + this.stg_kz = stg_kz + + const student_uid = root.getAttribute("student_uid_prop"); + this.student_uid = student_uid + + }, + template: ` + + ` +}); +app.config.globalProperties.$capitalize = capitalize; +app.use(primevue.config.default, { + zIndex: { + overlay: 9000, + tooltip: 8000 + } +}) +app.directive('tooltip', primevue.tooltip); +app.use(PluginsPhrasen); +app.mount('#abgabetoolroot'); diff --git a/public/js/apps/Dashboard/Fhc.js b/public/js/apps/Dashboard/Fhc.js index 190ed1a93..540a74f06 100644 --- a/public/js/apps/Dashboard/Fhc.js +++ b/public/js/apps/Dashboard/Fhc.js @@ -14,6 +14,7 @@ import Info from "../../components/Cis/Mylv/Semester/Studiengang/Lv/Info.js"; import RoomInformation, {DEFAULT_MODE_RAUMINFO} from "../../components/Cis/Mylv/RoomInformation.js"; import AbgabetoolStudent from "../../components/Cis/Abgabetool/AbgabetoolStudent.js"; import AbgabetoolMitarbeiter from "../../components/Cis/Abgabetool/AbgabetoolMitarbeiter.js"; +import AbgabetoolAssistenz from "../../components/Cis/Abgabetool/AbgabetoolAssistenz.js"; import DeadlineOverview from "../../components/Cis/Abgabetool/DeadlineOverview.js"; import Studium from "../../components/Cis/Studium/Studium.js"; @@ -56,6 +57,12 @@ const router = VueRouter.createRouter({ component: AbgabetoolMitarbeiter, props: true }, + { + path: `/Cis/Abgabetool/Assistenz/:stg_kz_prop?`, + name: 'AbgabetoolAssistenz', + component: AbgabetoolAssistenz, + props: true + }, { path: `/Cis/Abgabetool/Deadlines/:person_uid_prop?`, name: 'DeadlineOverview', @@ -228,13 +235,16 @@ const app = Vue.createApp({ components: {}, computed: { isMobile() { - return /Mobi|Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); + const smallScreen = window.matchMedia("(max-width: 767px)").matches; + const touchCapable = ("ontouchstart" in window) || navigator.maxTouchPoints > 0; + return smallScreen;// && touchCapable; } }, provide() { return { // provide injectable & watchable language property language: Vue.computed(() => this.$p.user_language), renderers: Vue.computed(() => this.renderers), + isMobile: this.isMobile } }, methods: { @@ -273,6 +283,7 @@ const app = Vue.createApp({ } }, async created(){ + await this.$api .call(ApiRenderers.loadRenderers()) .then(res => res.data) @@ -313,6 +324,7 @@ const app = Vue.createApp({ }, mounted() { document.addEventListener('click', this.handleClick); + }, beforeUnmount() { document.removeEventListener('click', this.handleClick); diff --git a/public/js/components/Bootstrap/Modal.js b/public/js/components/Bootstrap/Modal.js index a84d9d8d7..15253cfe8 100644 --- a/public/js/components/Bootstrap/Modal.js +++ b/public/js/components/Bootstrap/Modal.js @@ -46,7 +46,8 @@ export default { "hiddenBsModal", "hidePreventedBsModal", "showBsModal", - "shownBsModal" + "shownBsModal", + "toggleFullscreen" ], methods: { dispose() { @@ -66,6 +67,7 @@ export default { }, toggleFullscreen() { this.fullscreen = !this.fullscreen + this.$emit('toggleFullscreen') } }, mounted() { diff --git a/public/js/components/Bootstrap/Offcanvas.js b/public/js/components/Bootstrap/Offcanvas.js new file mode 100644 index 000000000..aab2c55f5 --- /dev/null +++ b/public/js/components/Bootstrap/Offcanvas.js @@ -0,0 +1,151 @@ +export default { + name: 'BootstrapOffcanvas', + data: () => ({ + offcanvas: null + }), + props: { + backdrop: { + type: [Boolean, String], + default: true, + validator(value) { + return ['static', true, false].includes(value); + } + }, + keyboard: { + type: Boolean, + default: true + }, + scroll: { + type: Boolean, + default: false + }, + placement: { + type: String, + default: 'start', // start | end | top | bottom + validator(value) { + return ['start', 'end', 'top', 'bottom'].includes(value); + } + }, + noCloseBtn: Boolean, + headerClass: { + type: [String, Array, Object], + default: '' + }, + bodyClass: { + type: [String, Array, Object], + default: 'p-4' + }, + footerClass: { + type: [String, Array, Object], + default: '' + }, + dialogClass: [String, Array, Object] + }, + emits: [ + "hideBsOffcanvas", + "hiddenBsOffcanvas", + "hidePreventedBsOffcanvas", + "showBsOffcanvas", + "shownBsOffcanvas" + ], + methods: { + dispose() { + return this.offcanvas?.dispose(); + }, + hide() { + return this.offcanvas?.hide(); + }, + show(relatedTarget) { + return this.offcanvas?.show(relatedTarget); + }, + toggle() { + return this.offcanvas?.toggle(); + }, + popup(body, options, title, footer) { + const BsOffcanvas = this, + slots = {}; + + if (body !== undefined) + slots.default = () => body; + if (title !== undefined) + slots.title = () => title; + if (footer !== undefined) + slots.footer = () => footer; + + let includedPrimevue = false; + if (typeof primevue !== 'undefined') + includedPrimevue = true; + + return new Promise((resolve, reject) => { + const instance = Vue.createApp({ + name: 'OffcanvasTmpApp', + setup() { + return () => + Vue.h(BsOffcanvas, { + class: 'offcanvas-wrapper', + ref: 'offcanvas', + ...options + }, slots); + }, + mounted() { + this.$refs.offcanvas.show(); + }, + beforeUnmount() { + if (this.$refs.offcanvas) + this.$refs.offcanvas.result !== false ? resolve(this.$refs.offcanvas.result) : reject(); + }, + unmounted() { + wrapper.parentElement.removeChild(wrapper); + } + }); + const wrapper = document.createElement('div'); + + if (includedPrimevue) { + instance.use(primevue.config.default, { zIndex: { overlay: 9999 } }); + } + + import('../../plugins/Phrasen.js').then((Phrasen) => { + instance.use(Phrasen.default); + instance.mount(wrapper); + document.body.appendChild(wrapper); + }); + }); + } + }, + mounted() { + if (this.$refs.offcanvas) { + this.offcanvas = new bootstrap.Offcanvas(this.$refs.offcanvas, { + backdrop: this.backdrop, + keyboard: this.keyboard, + scroll: this.scroll + }); + } + }, + template: ` +
+
+
+ +
+ +
+ +
+ +
+ + +
+ ` +} diff --git a/public/js/components/Chart/FhcChart.js b/public/js/components/Chart/FhcChart.js index 0733811f1..723ac0159 100644 --- a/public/js/components/Chart/FhcChart.js +++ b/public/js/components/Chart/FhcChart.js @@ -8,12 +8,6 @@ export const FhcChart = { }, template: `
-
- - - - -
diff --git a/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js index 0900282ef..35633321d 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 = { @@ -10,90 +11,245 @@ export const AbgabeMitarbeiterDetail = { Checkbox: primevue.checkbox, Dropdown: primevue.dropdown, Textarea: primevue.textarea, + SpeedDial: primevue.speeddial, + Accordion: primevue.accordion, + AccordionTab: primevue.accordiontab, + Message: primevue.message, VueDatePicker }, + inject: [ + 'abgabeTypeOptions', + 'abgabetypenBetreuer', + 'allowedNotenOptions', + 'turnitin_link', + 'old_abgabe_beurteilung_link' + ], props: { projektarbeit: { type: Object, default: null + }, + isFullscreen: { + type: Boolean, + default: false + }, + assistenzMode: { + type: Boolean, + default: false } }, data() { return { - oldPaBeurteilungLink: 'https://moodle.technikum-wien.at/mod/page/view.php?id=1005052', // TODO: inject from app & app provide link from config + showAutomagicModalPhrase: false, 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' - } - ] + speedDialItems: [{ + label: Vue.computed(() => this.$p.t('abgabetool/c4newAbgabetermin')), + icon: "fa fa-plus", + command: this.openCreateNewAbgabeModal, + disabled: Vue.computed(() => this.projektarbeit?.betreuerart_kurzbz == 'Zweitbegutachter') + }, + { + label: Vue.computed(() => this.$p.t('abgabetool/c4benoten')), + icon: "fa fa-user-check", + command: this.openBenotung, + disabled: Vue.computed(()=> this.assistenzMode == true) + }, + { + label: Vue.computed(() => this.$p.t('abgabetool/c4plagiatcheck_link')), + icon: "fa fa-clipboard-check", + command: this.openPlagiatcheck + }, + { + label: Vue.computed(() => this.$p.t('abgabetool/c4student_perspective')), + icon: "fa fa-eye", + command: this.openStudentPage + }], + newTermin: null, + form: Vue.reactive({ + sprache: '', + abstract: '', + abstract_en: '', + schlagwoerter: '', + schlagwoerter_en: '', + kontrollschlagwoerter: '', + seitenanzahl: 1, + }) } }, methods: { - openZusatzdatenModal(termin) { - + getNoteBezeichnung(termin){ + if(termin.note?.bezeichnung) { + return termin.note?.positiv ? this.$capitalize(this.$p.t('abgabetool/c4positivBenotet')) + ' ✅' : this.$capitalize(this.$p.t('abgabetool/c4negativBenotet')) + ' ❌' + } else if(termin.bezeichnung?.benotbar === true && !termin.note) { + return this.$capitalize(this.$p.t('abgabetool/c4notYetGraded')); + } else { + return '' + } + }, + getPlaceholderTermin(termin) { + return termin?.bezeichnung ? this.$p.t('abgabetool/c4paatyp' + termin.paabgabetyp_kurzbz) : this.$p.t('abgabetool/abgabetypPlaceholder') }, saveTermin(termin) { const paabgabe_id = termin.paabgabe_id - this.$fhcApi.factory.lehre.postProjektarbeitAbgabe(termin).then( (res) => { + termin.note_pk = termin.note?.note ?? null + termin.betreuer_person_id = this.projektarbeit.betreuer_person_id + + // phrasentext 'no late submission allowed' to 'late submission allowed' + boolean UI invert + termin.fixtermin = !termin.invertedFixtermin + return 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 - - this.projektarbeit.abgabetermine.push({ // new abgatermin row - - 'paabgabe_id': -1, - 'projektarbeit_id': this.projektarbeit.projektarbeit_id, - 'fixtermin': false, - 'kurzbz': '', - 'datum': new Date().toISOString().split('T')[0], - 'paabgabetyp_kurzbz': '', - 'bezeichnung': '', - 'abgabedatum': null, - 'insertvon': this.viewData?.uid ?? '', - 'allowedToSave': true, - 'allowedToDelete': true - }) + + const noteOpt = this.allowedNotenOptions.find(opt => opt.note == res.data[0].note) + const newTerminRes = { + 'allowedToSave': true, + 'allowedToDelete': true, + ...res.data[0] + } + if(newTerminRes.note) newTerminRes.note = noteOpt + newTerminRes.invertedFixtermin = !newTerminRes.fixtermin + const existingTerminRes = res.data[1] + + const abgabeOpt = this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz == newTerminRes.paabgabetyp_kurzbz) + + newTerminRes.bezeichnung = { + bezeichnung: termin.bezeichnung?.bezeichnung, + paabgabetyp_kurzbz: termin.bezeichnung?.paabgabetyp_kurzbz, + benotbar: abgabeOpt.benotbar } + + // only insert new abgabe if we actually created a new one, not when saving/editing existing + if(!existingTerminRes){ + this.projektarbeit.abgabetermine.push(newTerminRes) + } else { + const noteOptExisting = this.allowedNotenOptions.find(opt => opt.note == existingTerminRes.note) + existingTerminRes.note = noteOptExisting + } + + this.projektarbeit.abgabetermine.sort((a, b) =>new Date(a.datum) - new Date(b.datum)) + + const index = this.projektarbeit.abgabetermine.findIndex(t => termin.paabgabe_id == t.paabgabe_id) + + // negative abgabe -> automagically open new termin modal + // really bad feature imo that will be annoying to deal with + + // termin is completely new and has negative note + const savedNewWithNegative = !existingTerminRes && !newTerminRes.note?.positiv && newTerminRes.note !== null + + // termin existed previously + oldTermin had different note/positive note or no note at all + const savedExistingNoteAsNegativeAndWasNotNegativeBefore = existingTerminRes && !newTerminRes.note?.positiv && newTerminRes.note !== null && (existingTerminRes.note?.positiv || existingTerminRes.note === undefined) + + const openModalDueToNegativeBeurteilung = savedNewWithNegative || savedExistingNoteAsNegativeAndWasNotNegativeBefore + if(openModalDueToNegativeBeurteilung) { + this.newTermin = { + 'paabgabe_id': -1, + 'projektarbeit_id': this.projektarbeit.projektarbeit_id, + 'fixtermin': false, + 'invertedFixtermin': true, + 'kurzbz': '', // todo kurzbz textfield value vorschlag für qualgates + 'datum': new Date().toISOString().split('T')[0], + 'note': this.allowedNotenOptions.find(opt => opt.note == 9), + 'beurteilungsnotiz': '', + 'upload_allowed': false, + 'paabgabetyp_kurzbz': '', + 'bezeichnung': this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz === newTerminRes.paabgabetyp_kurzbz), + 'abgabedatum': null, + 'insertvon': this.viewData?.uid ?? '' + } + + this.showAutomagicModalPhrase = true + + this.$refs.modalContainerCreateNewAbgabe.show() + } else { + this.showAutomagicModalPhrase = false + } } else if(res?.meta?.status == 'error'){ this.$fhcAlert.alertError() } - }) }, + openZusatzdatenModal() { + this.$refs.modalContainerZusatzdaten.show() + }, + async saveZusatzdaten(){ + if (!await this.validateZusatzdaten()) + { + return false; + } + + const pa = this.projektarbeit + + // post endabgabe + const formData = new FormData(); + formData.append('projektarbeit_id', this.projektarbeit.projektarbeit_id); + + formData.append('sprache', this.form['sprache'].sprache) + formData.append('abstract', this.form['abstract']) + formData.append('abstract_en', this.form['abstract_en']) + formData.append('schlagwoerter', this.form['schlagwoerter']) + formData.append('schlagwoerter_en', this.form['schlagwoerter_en']) + formData.append('seitenanzahl', this.form['seitenanzahl']) + + this.loading = true + this.$api.call(ApiAbgabe.postStudentProjektarbeitZusatzdaten(formData)) + .then(res => { + if(res.meta.status == 'success') { + this.$fhcAlert.alertSuccess(this.$p.t('ui/gespeichert')) + if(!data?.retval?.[0]) return + const paRes = data.retval[0] + pa.seitenanzahl = paRes.seitenanzahl ?? 1 + pa.kontrollschlagwoerter = paRes.kontrollschlagwoerter ?? '' + pa.schlagwoerter = paRes.schlagwoerter ?? '' + pa.sprache = paRes.sprache ?? '' + pa.schlagwoerter_en = paRes.schlagwoerter_en ?? '' + pa.abstract = paRes.abstract ?? '' + pa.abstract_en = paRes.abstract_en ?? '' + } + + }).finally(()=> { + this.loading = false + }) + + this.$refs.modalContainerZusatzdaten.hide() + }, + async validateZusatzdaten() { + // just ask once + if(await this.$fhcAlert.confirm({ + message: this.$p.t('abgabetool/confirmZusatzdatenSpeichern'), + acceptLabel: this.$capitalize(this.$p.t('abgabetool/c4AcceptAndProceed')), + acceptClass: 'p-button-primary', + rejectLabel: this.$capitalize(this.$p.t('abgabetool/c4Cancel')), + rejectClass: 'p-button-secondary' + }) === false) { + return false + } + + return true + }, + async handleDeleteTermin(termin){ + if(await this.$fhcAlert.confirm({ + message: this.$p.t('abgabetool/c4confirm_delete'), + acceptLabel: 'Löschen', + acceptClass: 'p-button-danger', + rejectLabel: 'Zurück', + rejectClass: 'p-button-secondary' + }) === false) { + return false + } else { + this.deleteTermin(termin) + } + }, 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 ]) 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() } @@ -108,35 +264,79 @@ export const AbgabeMitarbeiterDetail = { return true; }, downloadAbgabe(termin) { - this.$fhcApi.factory.lehre.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid) + const url = `/api/frontend/v1/Abgabe/getStudentProjektarbeitAbgabeFile?paabgabe_id=${termin.paabgabe_id}&student_uid=${this.projektarbeit.student_uid}&projektarbeit_id=${this.projektarbeit.projektarbeit_id}`; + + window.open(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + url) + // this.$api.call(ApiAbgabe.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) + convertDateToIsoString(date) { + // 1. Check if it is a Date object AND if the date value is valid (not 'Invalid Date') + if (param instanceof Date && !isNaN(param.getTime())) { + const year = param.getFullYear(); + // getMonth() is 0-indexed, so we add 1. + const month = param.getMonth() + 1; + const day = param.getDate(); + + // Helper to pad single-digit numbers with a leading zero + const pad = (num) => String(num).padStart(2, '0'); + + // Return the formatted string: YYYY-MM-DD + return `${year}-${pad(month)}-${pad(day)}`; + } + + // If it's not a valid Date, return the original parameter + return param; }, - getDateStyle(termin) { + dateDiffInDays(datumParam){ + let datum = datumParam + if(datumParam instanceof Date && !isNaN(datum.getTime())) + { + const year = datumParam.getFullYear(); + const month = datumParam.getMonth() + 1; // getMonth() is 0-indexed + const day = datumParam.getDate(); + const pad = (num) => String(num).padStart(2, '0'); + datum = `${year}-${pad(month)}-${pad(day)}` + } + + const dateToday = luxon.DateTime.now().startOf('day'); + const dateDatum = luxon.DateTime.fromISO(datum).startOf('day'); + const duration = dateDatum.diff(dateToday, 'days'); + + return duration.values.days; + }, + getDateStyleClass(termin) { const datum = new Date(termin.datum) const abgabedatum = new Date(termin.abgabedatum) - // todo: rework styling but keep the color pattern logic - // https://wiki.fhcomplete.info/doku.php?id=cis:abgabetool_fuer_studierende - let color = 'white' - let fontColor = 'black' - if (termin.abgabedatum === null) { - if(datum < today) { - color = 'red' - fontColor = 'white' - } else if (datum > today && this.dateDiffInDays(datum, today) <= 12) { - color = 'yellow' - } - } else if(abgabedatum > datum) { - color = 'pink' // aka "hellrot" - fontColor = 'white' - } else { - color = 'green' + termin.diffindays = this.dateDiffInDays(termin.datum) + + const isLate = termin.abgabedatum && abgabedatum > datum; + + // GRADE STATUS + if (termin.note) { + if (termin.note.positiv) return 'bestanden'; + return 'nichtbestanden'; } - return `font-color: ${fontColor} ; background-color: ${color}; border-radius: 50%;` + // ACTION REQUIRED FOR GRADE + if (termin.bezeichnung?.benotbar && datum < today) { + return 'beurteilungerforderlich'; + } + + // SUBMISSION STATUS + if (termin.upload_allowed) { + if (termin.abgabedatum) { + return isLate ? 'verspaetet' : 'abgegeben'; + } + + // no submission yet + if (datum < today) return 'verpasst'; + if (termin.diffindays <= 12) return 'abzugeben'; + return 'standard'; + } + + // GENERIC STATUS + return datum < today ? 'verpasst' : 'standard'; }, openBeurteilungLink(link) { window.open(link, '_blank') @@ -144,9 +344,56 @@ export const AbgabeMitarbeiterDetail = { getOptionLabelSprache(option) { return option.sprache }, - getOptionLabelAbgabetyp(option){ + getOptionLabelAbgabetyp(option) { + return this.$p.t('abgabetool/c4paatyp' + option.paabgabetyp_kurzbz) + }, + getOptionDisabled(option) { + return !option.aktiv + }, + getNotenOptionLabel(option) { return option.bezeichnung }, + openStudentPage() { + const link = FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + + '/Cis/Abgabetool/Student/' + this.projektarbeit?.student_uid + window.open(link, '_blank') + }, + openPlagiatcheck() { + const link = this.turnitin_link + window.open(link, '_blank') + }, + async openBenotung() { + // old link check ? + + if(this.getSemesterBenotbar && this.projektarbeit?.abgabetermine.find(termin => termin.paabgabetyp_kurzbz == 'end' && termin.abgabedatum !== null) && this.projektarbeit?.beurteilungLinkNew) { + const link = this.projektarbeit?.beurteilungLinkNew + window.open(link, '_blank') + } else if(this.projektarbeit?.abgabetermine.find(termin => termin.paabgabetyp_kurzbz == 'end' && termin.abgabedatum !== null) && this.projektarbeit?.beurteilungLinkOld) { + if(await this.$fhcAlert.confirm({ + message: this.$p.t('abgabetool/c4aeltereParbeitBenotenv2'), + acceptLabel: this.$capitalize(this.$p.t('abgabetool/c4AcceptAndProceed')), + acceptClass: 'btn btn-danger', + rejectLabel: this.$capitalize(this.$p.t('abgabetool/c4Cancel')), + rejectClass: 'btn btn-outline-secondary' + }) === false) { + return false + } + + const link = this.projektarbeit?.beurteilungLinkOld + window.open(link, '_blank') + } else { + // show info text that no endupload with abgabe has been found + if(await this.$fhcAlert.confirm({ + message: this.$p.t('abgabetool/c4keinEnduploadErfolgt'), + acceptLabel: this.$capitalize(this.$p.t('abgabetool/c4AcceptAndProceed')), + acceptClass: 'btn btn-danger', + rejectLabel: this.$capitalize(this.$p.t('abgabetool/c4Cancel')), + rejectClass: 'btn btn-outline-secondary' + }) === false) { + return false + } + } + }, formatDate(dateParam) { const date = new Date(dateParam) // handle missing leading 0 @@ -155,26 +402,107 @@ export const AbgabeMitarbeiterDetail = { const month = padZero(date.getMonth() + 1); // Months are zero-based const day = padZero(date.getDate()); const year = date.getFullYear(); + + return `${day}.${month}.${year}` + }, + openCreateNewAbgabeModal() { + if(this.projektarbeit?.betreuerart_kurzbz == 'Zweitbegutachter') { + // maybe alert that this is not allowed or smth - return `${day}.${month}.${year}`; + this.$fhcAlert.alertWarning('Terminanlage disabled') + return + } + + if(!this.newTermin) { + const typ = this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz === 'zwischen') + this.newTermin = { + 'paabgabe_id': -1, + 'projektarbeit_id': this.projektarbeit.projektarbeit_id, + 'fixtermin': false, + 'invertedFixtermin': true, + 'kurzbz': '', + 'datum': new Date().toISOString().split('T')[0], + 'note': this.allowedNotenOptions.find(opt => opt.note == 9), + 'beurteilungsnotiz': '', + 'upload_allowed': typ.upload_allowed_default, + 'paabgabetyp_kurzbz': '', + 'bezeichnung': typ, + 'abgabedatum': null, + 'insertvon': this.viewData?.uid ?? '' + } + } + this.$refs.modalContainerCreateNewAbgabe.show() }, - openStudentPage() { - const link = FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router - + '/Cis/Abgabetool/Student/' + this.projektarbeit?.student_uid - window.open(link, '_blank') + validateTermin(termin) { + // compare new termin to existing ones to block illegal termin constellations, if they exist + + return true }, - openPlagiatcheck() { - // todo: hardcoded turnitin link? - const link = "https://technikum-wien.turnitin.com/sso/sp/redwood/saml/5IyfmBr2OcSIaWQTKlFCGj/start" - window.open(link, '_blank') + async handleSaveNewAbgabe(termin) { + + if(!this.validateTermin(termin)) { + this.$fhcAlert.alertWarning('invalid termin') + + return false + } + + await this.saveTermin(termin) + + this.$refs.modalContainerCreateNewAbgabe.hide() + this.newTermin = { + 'paabgabe_id': -1, + 'projektarbeit_id': this.projektarbeit.projektarbeit_id, + 'fixtermin': false, + 'invertedFixtermin': true, + 'kurzbz': '', + 'datum': new Date().toISOString().split('T')[0], + 'note': this.allowedNotenOptions.find(opt => opt.note == 9), + 'beurteilungsnotiz': '', + 'upload_allowed': false, + 'paabgabetyp_kurzbz': '', + 'bezeichnung': this.abgabeTypeOptions.find(opt => opt.paabgabetyp_kurzbz === 'zwischen'), + 'abgabedatum': null, + 'insertvon': this.viewData?.uid ?? '' + } + }, - openBenotung() { - const path = this.projektarbeit?.betreuerart_kurzbz == 'Zweitbegutachter' ? 'ProjektarbeitsbeurteilungZweitbegutachter' : 'ProjektarbeitsbeurteilungErstbegutachter' - const link = FHC_JS_DATA_STORAGE_OBJECT.app_root + 'index.ci.php/extensions/FHC-Core-Projektarbeitsbeurteilung/' + path - window.open(link, '_blank') + handleChangeAbgabetyp(termin) { + // if paabgabetype qualgate is selected, fill out kurzbz textfield with bezeichnung of quality gate so users + // are possibly less confused + if(termin.bezeichnung?.paabgabetyp_kurzbz === 'qualgate1' || termin.bezeichnung?.paabgabetyp_kurzbz === 'qualgate2') { + termin.kurzbz = termin.bezeichnung.bezeichnung + } else { + termin.kurzbz = '' + } } + }, computed: { + allowedToSaveZusatzdaten() { + return this.form.schlagwoerter.length > 0 && this.form.schlagwoerter_en.length > 0 && this.form.abstract.length > 0 && this.form.abstract_en.length > 0 && this.form.seitenanzahl > 0 + }, + getAllowedAbgabeTypeOptions() { + if(this.assistenzMode) { + return this.abgabeTypeOptions + } else { + return this.abgabeTypeOptions.filter(opt => this.abgabetypenBetreuer.includes(opt.paabgabetyp_kurzbz)) + } + }, + getMessagePtStyle() { + // adjust outer spacing and internal padding to appear similar to doenload button in size + return { + root: { + style: { + margin: '0px' + } + }, + wrapper: { + style: { + padding: '6px' + } + } + } + }, getEid() { return this.$p.t('abgabetool/c4eidesstattlicheErklaerung') }, @@ -186,8 +514,131 @@ 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 + }, + getSpeedDialStyle() { + return 'position: static !important;' + }, + getSpeedDialWrapperStyle() { + // non fullscreen -> wrapper is positioned on right bottom corner of modal, wherever that is + return 'position: absolute; z-index: 9999; left: 0px; bottom: 0.5rem;' + }, + getTooltipVerspaetet() { + return { + value: this.$p.t('abgabetool/c4tooltipVerspaetet'), + class: "custom-tooltip" + } + }, + getTooltipVerpasst() { + return { + value: this.$p.t('abgabetool/c4tooltipVerpasst'), + class: "custom-tooltip" + } + }, + getTooltipAbzugeben() { + return { + value: this.$p.t('abgabetool/c4tooltipAbzugeben'), + class: "custom-tooltip" + } + }, + getTooltipStandard() { + return { + value: this.$p.t('abgabetool/c4tooltipStandardv2'), + class: "custom-tooltip" + } + }, + getTooltipBeurteilungerforderlich() { + return { + value: this.$p.t('abgabetool/c4tooltipBeurteilungerforderlich'), + class: "custom-tooltip" + } + }, + getTooltipAbgegeben() { + return { + value: this.$p.t('abgabetool/c4tooltipAbgegeben'), + class: "custom-tooltip" + } + }, + getTooltipFixtermin() { + return { + value: this.$p.t('abgabetool/c4tooltipFixtermin'), + class: "custom-tooltip" + } + }, + getTooltipAbgabeDetected() { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipAbgabeDetected')), + class: "custom-tooltip" + } + }, + getTooltipNotAllowedToSave() { + return { + value: this.$p.t('abgabetool/c4notAllowedToEditAbgabeTermin'), + class: "custom-tooltip" + } + }, + getTooltipNotAllowedToDelete() { + return { + value: this.$p.t('abgabetool/c4notAllowedToDeleteAbgabeTermin'), + class: "custom-tooltip" + } + }, + getTooltipBestanden() { + return { + value: this.$p.t('abgabetool/c4tooltipBestanden'), + class: "custom-tooltip" + } + }, + getTooltipNichtBestanden() { + return { + value: this.$p.t('abgabetool/c4tooltipNichtBestanden'), + class: "custom-tooltip" + } + }, + getProjektarbeitTitel() { + if(this.projektarbeit?.titel) return this.$capitalize(this.$p.t('abgabetool/c4titel')) + ': ' + this.projektarbeit.titel + + return '' + }, + getProjektarbeitStudent(){ + + if(this.projektarbeit?.student) return this.$capitalize(this.$p.t('person/student')) + ': ' + this.projektarbeit.student + + return '' } - + }, + watch: { + 'newTermin.bezeichnung'(newVal) { + if(newVal?.paabgabetyp_kurzbz === 'qualgate1' || newVal?.paabgabetyp_kurzbz === 'qualgate2') { + this.newTermin.kurzbz = newVal.bezeichnung + } + + this.newTermin.upload_allowed = newVal.upload_allowed_default + }, + 'projektarbeit'(newVal) { + // set invertedFixtermin field for UI/UX purposes -> avoid double negation in text + + newVal?.abgabetermine?.forEach(termin => termin.invertedFixtermin = !termin.fixtermin) + + // default select german if projektarbeit sprache was null + this.form.sprache = newVal.sprache ? this.allActiveLanguages.find(lang => lang.sprache == newVal.sprache) : this.allActiveLanguages.find(lang => lang.sprache == 'German') + this.form.abstract = newVal.abstract ?? '' + this.form.abstract_en = newVal.abstract_en ?? '' + this.form.schlagwoerter = newVal.schlagwoerter ?? '' + this.form.schlagwoerter_en = newVal.schlagwoerter_en ?? '' + this.form.kontrollschlagwoerter = newVal.kontrollschlagwoerter ?? '' + this.form.seitenanzahl = newVal.seitenanzahl ?? 1 + + }, }, created() { @@ -196,71 +647,185 @@ export const AbgabeMitarbeiterDetail = { }, template: ` -
- - -
{{$p.t('abgabetool/c4abgabeMitarbeiterbereich')}}
- - -
-
-

{{projektarbeit?.student}}

-

{{projektarbeit?.titel}}

-

{{projektarbeit?.zweitbegutachter}}

-
-
-
-
- -
-
- - Kein Endupload vorhanden! -
-
-
-
- -
- -
-
-
- -
- -
-
+ + + + + + +
+
{{$capitalize( $p.t('abgabetool/c4abgabeMitarbeiterbereich') )}}
+ +
+
+

{{getProjektarbeitStudent}}

+

{{getProjektarbeitTitel}}

+ + +
+
+ + + +
+
+
+
+ + + + +
+
+ +
+
+ + + + +
+
{{ $capitalize( $p.t('abgabetool/c4keineAbgabetermineGefunden') )}}
+
+ + + + + + + +
`, }; diff --git a/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js b/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js index 1eb5d099c..55120e223 100644 --- a/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js +++ b/public/js/components/Cis/Abgabetool/AbgabeStudentDetail.js @@ -1,8 +1,9 @@ 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' +import FhcOverlay from "../../Overlay/FhcOverlay.js"; -const today = new Date() export const AbgabeStudentDetail = { name: "AbgabeStudentDetail", components: { @@ -12,8 +13,14 @@ export const AbgabeStudentDetail = { Checkbox: primevue.checkbox, Dropdown: primevue.dropdown, Textarea: primevue.textarea, - VueDatePicker + Accordion: primevue.accordion, + AccordionTab: primevue.accordiontab, + Message: primevue.message, + Inplace: primevue.inplace, + VueDatePicker, + FhcOverlay }, + inject: ['notenOptions', 'isMobile', 'isViewMode', 'moodle_link'], props: { projektarbeit: { type: Object, @@ -26,6 +33,7 @@ export const AbgabeStudentDetail = { }, data() { return { + loading: false, eidAkzeptiert: false, enduploadTermin: null, allActiveLanguages: FHC_JS_DATA_STORAGE_OBJECT.server_languages, @@ -41,16 +49,40 @@ export const AbgabeStudentDetail = { } }, methods: { - validate: function(termin) { + getNoteBezeichnung(termin){ + const noteOpt = this.notenOptions.find(opt => opt.note == termin.note) + + if(noteOpt?.bezeichnung) { + return noteOpt?.positiv ? this.$capitalize(this.$p.t('abgabetool/c4positivBenotet')) + ' ✅' : this.$capitalize(this.$p.t('abgabetool/c4negativBenotet')) + ' ❌' + } else if(noteOpt?.benotbar === true && !termin.note) { + return this.$capitalize(this.$p.t('abgabetool/c4notYetGraded')); + } else { + return '' + } + }, + async validate(termin, endupload = false) { if(!termin.file.length) { - this.$fhcAlert.alertWarning(this.$p.t('global/warningChooseFile')); + this.$fhcAlert.alertWarning(this.$capitalize(this.$p.t('global/warningChooseFile'))); return false } - + + if(endupload) { + if(await this.$fhcAlert.confirm({ + message: this.$p.t('abgabetool/confirmEnduploadSpeichern'), + acceptLabel: this.$capitalize(this.$p.t('abgabetool/c4AcceptAndProceed')), + acceptClass: 'p-button-primary', + rejectLabel: this.$capitalize(this.$p.t('abgabetool/c4Cancel')), + rejectClass: 'p-button-secondary' + }) === false) { + return false + } + } + return true; }, - triggerEndupload() { - if (!this.validate(this.enduploadTermin)) + async triggerEndupload() { + + if (!await this.validate(this.enduploadTermin, true)) { return false; } @@ -63,7 +95,6 @@ export const AbgabeStudentDetail = { formData.append('student_uid', this.projektarbeit.student_uid) formData.append('bperson_id', this.projektarbeit.bperson_id) - // TODO: validate/check for null etc. formData.append('sprache', this.form['sprache'].sprache) formData.append('abstract', this.form['abstract']) formData.append('abstract_en', this.form['abstract_en']) @@ -74,15 +105,21 @@ 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.loading = true + this.$api.call(ApiAbgabe.postStudentProjektarbeitEndupload(formData)) .then(res => { - this.handleUploadRes(res) - }) + this.handleUploadRes(res, this.enduploadTermin) + }).finally(()=> { + this.loading = false + }) this.$refs.modalContainerEnduploadZusatzdaten.hide() }, downloadAbgabe(termin) { - this.$fhcApi.factory.lehre.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid) + const url = `/api/frontend/v1/Abgabe/getStudentProjektarbeitAbgabeFile?paabgabe_id=${termin.paabgabe_id}&student_uid=${this.projektarbeit.student_uid}&projektarbeit_id=${this.projektarbeit.projektarbeit_id}`; + + window.open(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + url) + // this.$api.call(ApiAbgabe.getStudentProjektarbeitAbgabeFile(termin.paabgabe_id, this.projektarbeit.student_uid)) }, formatDate(dateParam) { const date = new Date(dateParam) @@ -93,16 +130,17 @@ export const AbgabeStudentDetail = { const day = padZero(date.getDate()); const year = date.getFullYear(); - return `${day}.${month}.${year}`; + return `${day}.${month}.${year}` }, - upload(termin) { + async upload(termin) { - if (!this.validate(termin)) + // only do this on endupload + if (! await this.validate(termin)) { return false; } - if(termin.bezeichnung === 'Endupload') { + if(termin.bezeichnung?.paabgabetyp_kurzbz === 'end') { // open endupload form modal for further inputs this.enduploadTermin = termin this.$refs.modalContainerEnduploadZusatzdaten.show() @@ -117,166 +155,401 @@ 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.loading = true + this.$api.call(ApiAbgabe.postStudentProjektarbeitZwischenabgabe(formData)) .then(res => { - this.handleUploadRes(res) - }) + this.handleUploadRes(res, termin) + }).finally(()=> { + this.loading = false + }) } }, - handleUploadRes(res) { + handleUploadRes(res, termin) { if(res.meta.status == "success") { - this.$fhcAlert.alertSuccess('File erfolgreich hochgeladen') + this.$fhcAlert.alertSuccess(this.$capitalize(this.$p.t('abgabetool/c4fileUploadSuccessv3'))) + + // update 'abgabedatum' for successful upload -> shows the pdf icon and date once set + termin.abgabedatum = new Date().toISOString().split('T')[0]; + if(res?.data?.signatur !== undefined) { + termin.signatur = res.data.signatur + } + } else { - this.$fhcAlert.alertError('File upload error') + this.$fhcAlert.alertError(this.$capitalize(this.$p.t('abgabetool/c4fileUploadErrorv3'))) } if(res.meta.signaturInfo) { this.$fhcAlert.alertInfo(res.meta.signaturInfo) } - }, - dateDiffInDays(datum, today){ - const oneDayMs = 1000 * 60 * 60 * 24 - return Math.round((new Date(datum) - new Date(today)) / oneDayMs) - }, - getDateStyle(termin, mode) { - const datum = new Date(termin.datum) - const abgabedatum = new Date(termin.abgabedatum) - // todo: rework styling but keep the color pattern logic - // 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%;` - if( typeof mode !== 'undefined' || mode === 'icon') { - return icon; - } else { - return 'abgabe-zieldatum-border-' + color; - } - }, - openBeurteilungLink(link) { - window.open(link, '_blank') }, getOptionLabel(option) { return option.sprache - } + }, + getTerminNoteBezeichnung(termin) { + const noteOpt = this.notenOptions.find(opt => opt.note == termin.note) + return noteOpt ? noteOpt.bezeichnung : '' + }, }, watch: { projektarbeit(newVal) { // default select german if projektarbeit sprache was null this.form.sprache = newVal.sprache ? this.allActiveLanguages.find(lang => lang.sprache == newVal.sprache) : this.allActiveLanguages.find(lang => lang.sprache == 'German') - this.form.abstract = newVal.abstract - this.form.abstract_en = newVal.abstract_en - this.form.schlagwoerter = newVal.schlagwoerter - this.form.schlagwoerter_en = newVal.schlagwoerter_en - this.form.kontrollschlagwoerter = newVal.kontrollschlagwoerter - this.form.seitenanzahl = newVal.seitenanzahl + this.form.abstract = newVal.abstract ?? '' + this.form.abstract_en = newVal.abstract_en ?? '' + this.form.schlagwoerter = newVal.schlagwoerter ?? '' + this.form.schlagwoerter_en = newVal.schlagwoerter_en ?? '' + this.form.kontrollschlagwoerter = newVal.kontrollschlagwoerter ?? '' + this.form.seitenanzahl = newVal.seitenanzahl ?? 1 + } }, computed: { - getEid() { - return this.$p.t('abgabetool/c4eidesstattlicheErklaerung') + getMoodleLink() { + return this.moodle_link + this.projektarbeit.studiengang_kz + }, + getMessagePtStyle() { + // adjust outer spacing and internal padding to appear similar to doenload button in size + return { + root: { + style: { + margin: '0px' + } + }, + wrapper: { + style: { + padding: '6px' + } + } + } + }, + getEid() { + return this.$capitalize(this.$p.t('abgabetool/c4eidesstattlicheErklaerung')) + }, + allowedToSaveZusatzdaten() { + return this.form.schlagwoerter.length > 0 && this.form.schlagwoerter_en.length > 0 && this.form.abstract.length > 0 && this.form.abstract_en.length > 0 && this.form.seitenanzahl > 0 + }, + getAllowedToSendEndupload() { + return this.eidAkzeptiert && this.allowedToSaveZusatzdaten + }, + qualityGateTerminAvailable() { + let qgatefound = false + this.projektarbeit?.abgabetermine.forEach(abgabe => { + if(abgabe.paabgabetyp_kurzbz == 'qualgate1' + || abgabe.paabgabetyp_kurzbz == 'qualgate2') { + qgatefound = true + } + }) + return qgatefound + }, + getTooltipVerspaetet() { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipVerspaetet')), + class: "custom-tooltip" + } + }, + getTooltipVerpasst() { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipVerpasst')), + class: "custom-tooltip" + } + }, + getTooltipAbzugeben() { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipAbzugeben')), + class: "custom-tooltip" + } + }, + getTooltipStandard() { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipStandardv2')), + class: "custom-tooltip" + } + }, + getTooltipAbgegeben() { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipAbgegeben')), + class: "custom-tooltip" + } + }, + getTooltipFixtermin() { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipFixtermin')), + class: "custom-tooltip" + } + }, + getTooltipAbgabeDetected() { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipAbgabeDetected')), + class: "custom-tooltip" + } + }, + getTooltipNotAllowedToUpload() { + if(this.isViewMode) { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4studentAbgabeNotAllowedInViewMode')), + class: "custom-tooltip" + } + } else { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4studentAbgabeNotAllowedRegular')), + class: "custom-tooltip" + } + } + }, + getTooltipBeurteilungerforderlich() { + return { + value: this.$capitalize(this.$p.t('abgabetool/c4tooltipBeurteilungerforderlich')), + class: "custom-tooltip" + } + }, + getTooltipBestanden() { + return { + value: this.$p.t('abgabetool/c4tooltipBestanden'), + class: "custom-tooltip" + } + }, + getTooltipNichtBestanden() { + return { + value: this.$p.t('abgabetool/c4tooltipNichtBestanden'), + class: "custom-tooltip" + } }, - getEnduploadErlaubt() { - return !this.eidAkzeptiert - } }, created() { - + }, mounted() { }, template: ` + +
-
{{$p.t('abgabetool/c4abgabeStudentenbereich')}}
+
{{$capitalize( $p.t('abgabetool/c4abgabeStudentenbereich') )}}
-

{{projektarbeit?.betreuer}}

-

{{projektarbeit?.titel}}

-
-
-
-
{{$p.t('abgabetool/c4fixtermin')}}
-
{{$p.t('abgabetool/c4zieldatum')}}
-
{{$p.t('abgabetool/c4abgabetyp')}}
-
{{$p.t('abgabetool/c4abgabekurzbz')}}
-
{{$p.t('abgabetool/c4abgabedatum')}}
-
- {{$p.t('abgabetool/c4fileupload')}} -
+
+

{{$capitalize( $p.t('person/student') ) }}: {{projektarbeit?.student}}

+

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

+

{{$capitalize( $p.t('abgabetool/c4betreuer') ) }}: {{projektarbeit ? $p.t('abgabetool/c4betrart' + projektarbeit.betreuerart_kurzbz) + ' ' + projektarbeit.betreuer : ''}}

-
-
- - - -
-
-
- - - -
-
-
{{ termin.bezeichnung }}
-
- -
-
- {{ termin.abgabedatum?.split("-").reverse().join(".") }} - - - -
-
-
-
- -
-
- -
-
-
+
+

{{ $p.t('abgabetool/c4checkoutStgMoodleInfos') }} + Moodle +

+ + + + + +
+
{{ $capitalize( $p.t('abgabetool/c4keineAbgabetermineGefunden') )}}
+
+
- +