diff --git a/application/config/stv.php b/application/config/stv.php index 8942c35e6..34a30a96e 100644 --- a/application/config/stv.php +++ b/application/config/stv.php @@ -130,3 +130,16 @@ $config['students_tab_order'] = [ 'combinePeople', 'archive', ]; + +$config['stv_prestudent_tags'] = [ + 'prioone' => ['readonly' => false], + 'priotwo' => ['readonly' => true], + 'hinweis' => ['readonly' => false], + 'hinweis_assistenz' => ['readonly' => true], + 'hinweis_kf' => ['readonly' => true], + 'hinweis_lehrende' => ['readonly' => false], + 'hinweis_stg_kf' => ['readonly' => true], + 'finished_stg' => ['readonly' => true], + 'finished_kf' => ['readonly' => true], + 'inwork_kf' => ['readonly' => true], +]; diff --git a/application/controllers/api/frontend/v1/notiz/NotizAnrechnung.php b/application/controllers/api/frontend/v1/notiz/NotizAnrechnung.php new file mode 100644 index 000000000..30dae9a50 --- /dev/null +++ b/application/controllers/api/frontend/v1/notiz/NotizAnrechnung.php @@ -0,0 +1,44 @@ + ['admin:r', 'assistenz:r'], + ]); + + //Load Models + $this->load->model('person/Notiz_model', 'NotizModel'); + $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel'); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + // Load language phrases + $this->loadPhrases([ + 'ui' + ]); + } + + public function isBerechtigt($id, $typeId) + { + if($typeId != "anrechnung_id") + { + $this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL); + } + + //TODO define permission + if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid')) + { + $result = $this->p->t('lehre','error_keineSchreibrechte'); + + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess("berechtigt in überschreibender Funktion"); + } +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/notiz/NotizBestellung.php b/application/controllers/api/frontend/v1/notiz/NotizBestellung.php new file mode 100644 index 000000000..e30628f33 --- /dev/null +++ b/application/controllers/api/frontend/v1/notiz/NotizBestellung.php @@ -0,0 +1,43 @@ + ['admin:r', 'assistenz:r'], + ]); + + //Load Models + $this->load->model('person/Notiz_model', 'NotizModel'); + $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel'); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + // Load language phrases + $this->loadPhrases([ + 'ui' + ]); + } + + public function isBerechtigt($id, $typeId) + { + if($typeId != "bestellung_id") + { + $this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL); + } + //TODO define permission + if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid')) + { + $result = $this->p->t('lehre','error_keineSchreibrechte'); + + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess("berechtigt in überschreibender Funktion"); + } +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/notiz/NotizLehreinheit.php b/application/controllers/api/frontend/v1/notiz/NotizLehreinheit.php index f8e1f816b..a3b96d477 100644 --- a/application/controllers/api/frontend/v1/notiz/NotizLehreinheit.php +++ b/application/controllers/api/frontend/v1/notiz/NotizLehreinheit.php @@ -17,5 +17,106 @@ class NotizLehreinheit extends Notiz_Controller 'getMitarbeiter' => ['admin:r', 'assistenz:r'], 'isBerechtigt' => ['admin:r', 'assistenz:r'], ]); + + //Load Models + $this->load->model('person/Notiz_model', 'NotizModel'); + $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel'); + $this->load->model('education/Lehreinheit_model', 'LehreinheitModel'); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + //Permission checks for allowed Oes + $allowedOes = $this->permissionlib->getOE_isEntitledFor('assistenz') ?: []; + + if ($this->router->method == 'addNewNotiz') + { + $json = $this->input->post('data'); + $post_data = json_decode($json, true); + $lehreinheit_id = $post_data['id']; + + if(!$lehreinheit_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Lehreinheit ID']), self::ERROR_TYPE_GENERAL); + } + $this->_checkAllowedOesFromLehreinheit($lehreinheit_id, $allowedOes); + } + + if ($this->router->method == 'updateNotiz') + { + $json = $this->input->post('data'); + $post_data = json_decode($json, true); + $notiz_id = $post_data['notiz_id']; + + if(!$notiz_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Notiz ID']), self::ERROR_TYPE_GENERAL); + } + + //get lehreinheit_id + $result = $this->NotizzuordnungModel->loadWhere(['notiz_id' => $notiz_id]); + + $data = $this->getDataOrTerminateWithError($result); + $lehreinheit_id = current($data)->lehreinheit_id; + + if(!$lehreinheit_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Lehreinheit ID']), self::ERROR_TYPE_GENERAL); + } + $this->_checkAllowedOesFromLehreinheit($lehreinheit_id, $allowedOes); + } + + if ($this->router->method == 'deleteNotiz') + { + $notiz_id = $this->input->post('notiz_id'); + $lehreinheit_id = $this->input->post('id'); + + if(!$notiz_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Notiz ID']), self::ERROR_TYPE_GENERAL); + } + + if(!$lehreinheit_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Lehreinheit ID']), self::ERROR_TYPE_GENERAL); + } + $this->_checkAllowedOesFromLehreinheit($lehreinheit_id, $allowedOes); + } + + // Load language phrases + $this->loadPhrases([ + 'ui' + ]); } -} \ No newline at end of file + + private function _checkAllowedOesFromLehreinheit($lehreinheit_id, $allowedOes) + { + //get oe from lehreinheit + $result = $this->LehreinheitModel->getOes($lehreinheit_id); + $data = $this->getDataOrTerminateWithError($result); + $oes = current($data); + + if (!in_array($oes, $allowedOes)) + { + return $this->terminateWithError($this->p->t('ui', 'error_keineBerechtigungStg') . " " . $oes, self::ERROR_TYPE_GENERAL); + } + } + + public function isBerechtigt($id, $typeId) + { + if($typeId != "lehreinheit_id") + { + $this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL); + } + + if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid')) + { + $result = $this->p->t('lehre','error_keineSchreibrechte'); + + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess("berechtigt in überschreibender Funktion"); + } + + +} diff --git a/application/controllers/api/frontend/v1/notiz/NotizMitarbeiter.php b/application/controllers/api/frontend/v1/notiz/NotizMitarbeiter.php new file mode 100644 index 000000000..f7de4b47b --- /dev/null +++ b/application/controllers/api/frontend/v1/notiz/NotizMitarbeiter.php @@ -0,0 +1,44 @@ + ['admin:r', 'assistenz:r'], + ]); + + //Load Models + $this->load->model('person/Notiz_model', 'NotizModel'); + $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel'); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + // Load language phrases + $this->loadPhrases([ + 'ui' + ]); + } + + public function isBerechtigt($id, $typeId) + { + if($typeId != "mitarbeiter_uid") + { + $this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL); + } + + //TODO define permission + if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid')) + { + $result = $this->p->t('lehre','error_keineSchreibrechte'); + + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess("berechtigt in überschreibender Funktion"); + } +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/notiz/NotizPerson.php b/application/controllers/api/frontend/v1/notiz/NotizPerson.php index 23a8fd199..7f0645bc6 100644 --- a/application/controllers/api/frontend/v1/notiz/NotizPerson.php +++ b/application/controllers/api/frontend/v1/notiz/NotizPerson.php @@ -20,33 +20,123 @@ class NotizPerson extends Notiz_Controller 'isBerechtigt' => ['admin:r', 'assistenz:r'], 'getCountNotes' => ['admin:r', 'assistenz:r'], ]); + + //Load Models + $this->load->model('person/Benutzer_model', 'BenutzerModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + + //Permission checks for allowed Oes + if ($this->router->method == 'addNewNotiz') + { + $json = $this->input->post('data'); + $post_data = json_decode($json, true); + $person_id = $post_data['id']; + + $allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []; + + if(!$person_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID']), self::ERROR_TYPE_GENERAL); + } + $this->_checkIfBerechtigungForOneUidExists($person_id, $allowedStgs); + } + + if ( $this->router->method == 'updateNotiz') + { + $json = $this->input->post('data'); + $post_data = json_decode($json, true); + $notiz_id = $post_data['notiz_id']; + + if(!$notiz_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Notiz ID']), self::ERROR_TYPE_GENERAL); + } + + //get person_id + $result = $this->NotizzuordnungModel->loadWhere(['notiz_id' => $notiz_id]); + + $data = $this->getDataOrTerminateWithError($result); + $person_id = current($data)->person_id; + + $allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []; + $this->_checkIfBerechtigungForOneUidExists($person_id, $allowedStgs); + } + + if ($this->router->method == 'deleteNotiz' ) + { + $notiz_id = $this->input->post('notiz_id'); + $person_id = $this->input->post('id'); + + if(!$notiz_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Notiz ID']), self::ERROR_TYPE_GENERAL); + } + + if(!$person_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'person ID']), self::ERROR_TYPE_GENERAL); + } + + $allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []; + $this->_checkIfBerechtigungForOneUidExists($person_id, $allowedStgs); + } } public function isBerechtigt($id, $typeId) { if($typeId != "person_id") { - return $this->terminateWithError($this->p->t('ui', 'error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL); + $this->terminateWithError($this->p->t('ui', 'error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL); } - //TODO define permission if (!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid')) { $result = $this->p->t('lehre', 'error_keineSchreibrechte'); - - return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); } - return $this->outputJsonSuccess(true); + $this->terminateWithSuccess("berechtigt in überschreibender Funktion"); } - public function loadDokumente() + //stv: if person has permission of one studiengang of person -> permission to add/update/delete Note + private function _checkIfBerechtigungForOneUidExists($person_id, $allowedStgs) { - $notiz_id = $this->input->post('notiz_id'); + //get all studentUids of person_id + $result = $this->BenutzerModel->loadWhere(['person_id' => $person_id]); + $data = $this->getDataOrTerminateWithError($result); - // TODO(chris): make CI variant of endpoint - $this->NotizModel->addSelect($this->NotizModel->escape(base_url('content/notizdokdownload.php?id=')) . ' || campus.tbl_dms_version.dms_id AS preview'); - - return parent::loadDokumente(); + $checkarray = []; + foreach ($data as $item) + { + //check if isStudent + $result = $this->StudentModel->isStudent($item->uid); + + $isStudent = $this->getDataOrTerminateWithError($result); + if($isStudent) + { + $checkarray[] = $this->_checkAllowedStgsFromUid($item->uid, $allowedStgs); + } + + } + if (!in_array(1, $checkarray)) + return $this->terminateWithError($this->p->t('ui', 'error_keineBerechtigungStg'), self::ERROR_TYPE_GENERAL); } -} \ No newline at end of file + + private function _checkAllowedStgsFromUid($student_uid, $allowedStgs) + { + $this->load->model('crm/Student_model', 'StudentModel'); + $result = $this->StudentModel->loadWhere(['student_uid' => $student_uid]); + + $data = $this->getDataOrTerminateWithError($result); + $studiengang_kz = current($data)->studiengang_kz; + + if (!in_array($studiengang_kz, $allowedStgs)) + { + return 0; + } + else + { + return 1; + } + } +} diff --git a/application/controllers/api/frontend/v1/notiz/NotizPrestudent.php b/application/controllers/api/frontend/v1/notiz/NotizPrestudent.php new file mode 100644 index 000000000..5e6cd747c --- /dev/null +++ b/application/controllers/api/frontend/v1/notiz/NotizPrestudent.php @@ -0,0 +1,117 @@ + ['admin:r', 'assistenz:r'], + ]); + + //Load Models + $this->load->model('person/Notiz_model', 'NotizModel'); + $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel'); + $this->load->model('crm/Student_model', 'StudentModel'); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + // Load language phrases + $this->loadPhrases([ + 'ui' + ]); + + //Permission checks for Studiengangsarray + $allowedStgs = $this->permissionlib->getSTG_isEntitledFor('assistenz') ?: []; + + if ($this->router->method == 'addNewNotiz') + { + $json = $this->input->post('data'); + $post_data = json_decode($json, true); + $prestudent_id = $post_data['id']; + + if(!$prestudent_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Lehreinheit ID']), self::ERROR_TYPE_GENERAL); + } + $this->_checkAllowedOesFromPrestudent($prestudent_id, $allowedStgs); + } + + if ($this->router->method == 'updateNotiz') + { + $json = $this->input->post('data'); + $post_data = json_decode($json, true); + $notiz_id = $post_data['notiz_id']; + + if(!$notiz_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Notiz ID']), self::ERROR_TYPE_GENERAL); + } + + //get prestudent_id + $result = $this->NotizzuordnungModel->loadWhere(['notiz_id' => $notiz_id]); + + $data = $this->getDataOrTerminateWithError($result); + $prestudent_id = current($data)->prestudent_id; + + if(!$prestudent_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + } + $this->_checkAllowedOesFromPrestudent($prestudent_id, $allowedStgs); + } + + if ($this->router->method == 'deleteNotiz') + { + $notiz_id = $this->input->post('notiz_id'); + $prestudent_id = $this->input->post('id'); + + if(!$notiz_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Notiz ID']), self::ERROR_TYPE_GENERAL); + } + + if(!$prestudent_id) + { + return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Prestudent ID']), self::ERROR_TYPE_GENERAL); + } + $this->_checkAllowedOesFromPrestudent($prestudent_id, $allowedStgs); + } + } + + public function isBerechtigt($id, $typeId) + { + if($typeId != "prestudent_id") + { + $this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL); + } + + if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid')) + { + $result = $this->p->t('lehre','error_keineSchreibrechte'); + + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess("berechtigt in überschreibender Funktion"); + } + + private function _checkAllowedOesFromPrestudent($prestudent_id, $allowedStgs) + { + $student_uid = $this->StudentModel->getUID($prestudent_id); + + $result = $this->StudentModel->loadWhere(['student_uid' => $student_uid]); + + $data = $this->getDataOrTerminateWithError($result); + $studiengang_kz = current($data)->studiengang_kz; + + if (!in_array($studiengang_kz, $allowedStgs)) + { + return $this->terminateWithError($this->p->t('ui', 'error_keineBerechtigungStg'), self::ERROR_TYPE_GENERAL); + } + } + +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/notiz/NotizProjekt.php b/application/controllers/api/frontend/v1/notiz/NotizProjekt.php new file mode 100644 index 000000000..9cdde36ae --- /dev/null +++ b/application/controllers/api/frontend/v1/notiz/NotizProjekt.php @@ -0,0 +1,32 @@ + ['admin:r', 'assistenz:r'], + ]); + } + + public function isBerechtigt($id, $typeId) + { + if($typeId != "projekt_kurzbz") + { + $this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL); + } + + //TODO define permission + if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid')) + { + $result = $this->p->t('lehre','error_keineSchreibrechte'); + + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess("berechtigt in überschreibender Funktion"); + } +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/notiz/NotizProjektphase.php b/application/controllers/api/frontend/v1/notiz/NotizProjektphase.php new file mode 100644 index 000000000..7a82c658e --- /dev/null +++ b/application/controllers/api/frontend/v1/notiz/NotizProjektphase.php @@ -0,0 +1,32 @@ + ['admin:r', 'assistenz:r'], + ]); + } + + public function isBerechtigt($id, $typeId) + { + if($typeId != "projektphase_id") + { + $this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL); + } + + //TODO define permission + if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid')) + { + $result = $this->p->t('lehre','error_keineSchreibrechte'); + + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess("berechtigt in überschreibender Funktion"); + } +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/notiz/NotizProjekttask.php b/application/controllers/api/frontend/v1/notiz/NotizProjekttask.php new file mode 100644 index 000000000..aadb04f40 --- /dev/null +++ b/application/controllers/api/frontend/v1/notiz/NotizProjekttask.php @@ -0,0 +1,32 @@ + ['admin:r', 'assistenz:r'], + ]); + } + + public function isBerechtigt($id, $typeId) + { + if($typeId != "projekttask_id") + { + $this->terminateWithError($this->p->t('ui','error_typeNotizIdIncorrect'), self::ERROR_TYPE_GENERAL); + } + + //TODO define permission + if(!$this->permissionlib->isBerechtigt('admin', 'suid') && !$this->permissionlib->isBerechtigt('assistenz', 'suid')) + { + $result = $this->p->t('lehre','error_keineSchreibrechte'); + + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + } + $this->terminateWithSuccess("berechtigt in überschreibender Funktion"); + } +} \ No newline at end of file diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index 9dbea65f2..c7e34c669 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -611,7 +611,7 @@ class Students extends FHCAPI_Controller if (!$verband && !$gruppe && $orgform_kurzbz !== null) { $this->PrestudentModel->db->where( "( - SELECT orgform_kurzbz + SELECT orgform_kurzbz FROM public.tbl_prestudentstatus WHERE prestudent_id=tbl_prestudent.prestudent_id AND studiensemester_kurzbz=" . $this->PrestudentModel->escape($studiensemester_kurzbz) . " @@ -855,6 +855,41 @@ class Students extends FHCAPI_Controller { $stdsemEsc = $studiensemester_kurzbz ? $this->PrestudentModel->escape($studiensemester_kurzbz) : 'NULL'; + $this->load->config('stv'); + $tags = $this->config->item('stv_prestudent_tags'); + + $whereTags = ''; + if (is_array($tags) && !isEmptyArray($tags)) { + $tags = array_keys($tags); + + foreach ($tags as $key => $tag) { + $tags[$key] = $this->db->escape($tag); + } + $whereTags = " AND nt.typ_kurzbz IN (" . implode(",", $tags) . ")"; + } + $subQueryTag = " + ( + SELECT + tag.prestudent_id, + COALESCE(json_agg(tag ORDER BY tag.done), '[]'::json) AS tags + FROM ( + SELECT DISTINCT ON (n.notiz_id) + n.notiz_id AS id, + nt.typ_kurzbz, + array_to_json(nt.bezeichnung_mehrsprachig)->>0 AS beschreibung, + n.text AS notiz, + nt.style, + n.erledigt AS done, + nz.prestudent_id + FROM public.tbl_notizzuordnung AS nz + JOIN public.tbl_notiz AS n ON nz.notiz_id = n.notiz_id + JOIN public.tbl_notiz_typ AS nt ON n.typ = nt.typ_kurzbz " + . $whereTags . + " + ) AS tag + GROUP BY tag.prestudent_id + ) AS tag_data_agg + "; $this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); $this->PrestudentModel->addJoin('public.tbl_person p', 'person_id'); @@ -877,8 +912,11 @@ class Students extends FHCAPI_Controller AND ps.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ') AND ps.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')', 'LEFT'); + $this->PrestudentModel->addJoin($subQueryTag, 'tag_data_agg.prestudent_id = tbl_prestudent.prestudent_id', 'LEFT'); + $this->PrestudentModel->addSelect("b.uid"); + $this->PrestudentModel->addSelect('tag_data_agg.tags'); $this->PrestudentModel->addSelect('titelpre'); $this->PrestudentModel->addSelect('nachname'); $this->PrestudentModel->addSelect('vorname'); diff --git a/application/controllers/api/frontend/v1/stv/Tags.php b/application/controllers/api/frontend/v1/stv/Tags.php new file mode 100644 index 000000000..3004a1f3b --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Tags.php @@ -0,0 +1,48 @@ + self::BERECHTIGUNG_KURZBZ, + 'getTags' => self::BERECHTIGUNG_KURZBZ, + 'addTag' => self::BERECHTIGUNG_KURZBZ, + 'updateTag' => self::BERECHTIGUNG_KURZBZ, + 'doneTag' => self::BERECHTIGUNG_KURZBZ, + 'deleteTag' => self::BERECHTIGUNG_KURZBZ + ]); + + $this->config->load('stv'); + } + + public function getTag($readonly_tags = null) + { + parent::getTag($this->config->item('stv_prestudent_tags')); + } + public function getTags($tags = null) + { + parent::getTags($this->config->item('stv_prestudent_tags')); + } + public function addTag($withZuordnung = true, $updatable_tags = null) + { + parent::addTag(true, $this->config->item('stv_prestudent_tags')); + } + public function updateTag($updatable_tags = null) + { + parent::updateTag($this->config->item('stv_prestudent_tags')); + } + public function deleteTag($withZuordnung = true, $updatable_tags = null) + { + parent::deleteTag(true, $this->config->item('stv_prestudent_tags')); + } + public function doneTag($updatable_tags = null) + { + parent::doneTag($this->config->item('stv_prestudent_tags')); + } +} diff --git a/application/core/Notiz_Controller.php b/application/core/Notiz_Controller.php index cfc54d5f5..923970923 100644 --- a/application/core/Notiz_Controller.php +++ b/application/core/Notiz_Controller.php @@ -8,7 +8,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller { const DEFAULT_PERMISSION_R = 'admin:r'; const DEFAULT_PERMISSION_RW = 'admin:rw'; - //public function __construct($zuordnung = 'person/Notizzuordnung_model') + public function __construct($permissions) { $default_permissions = [ @@ -97,13 +97,13 @@ abstract class Notiz_Controller extends FHCAPI_Controller if (isError($result)) { $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); } - return $this->terminateWithSuccess(getData($result) ?: []); + $this->terminateWithSuccess(getData($result) ?: []); } //Override function protected function isBerechtigt($id, $typeId){ - return $this->terminateWithError("in abstract function: define right in extension", self::ERROR_TYPE_GENERAL); + $this->terminateWithError("in abstract function: define right in extension", self::ERROR_TYPE_GENERAL); } public function loadNotiz() @@ -112,7 +112,6 @@ abstract class Notiz_Controller extends FHCAPI_Controller $notiz_id = $this->input->post('notiz_id'); - //$this->load->model('person/Notiz_model', 'NotizModel'); $this->NotizModel->addJoin('public.tbl_notiz_dokument', 'notiz_id', 'LEFT'); $this->NotizModel->addSelect('*'); $this->NotizModel->addSelect("TO_CHAR(CASE WHEN public.tbl_notiz.updateamum >= public.tbl_notiz.insertamum @@ -143,14 +142,9 @@ abstract class Notiz_Controller extends FHCAPI_Controller $uid = getAuthUID(); - if (isset($_POST['data'])) - { - $data = json_decode($_POST['data']); - unset($_POST['data']); - foreach ($data as $k => $v) { - $_POST[$k] = $v; - } - } + $json = $this->input->post('data'); + $post_data = json_decode($json, true); + $this->form_validation->set_data($post_data); //Form Validation $this->form_validation->set_rules('titel', 'Titel', 'required', [ @@ -166,26 +160,25 @@ abstract class Notiz_Controller extends FHCAPI_Controller $this->terminateWithValidationErrors($this->form_validation->error_array()); } - $titel = $this->input->post('titel'); - $text = $this->input->post('text'); - $erledigt = $this->input->post('erledigt'); - $verfasser_uid = isset($_POST['verfasser']) ? $_POST['verfasser'] : $uid; - $bearbeiter_uid = isset($_POST['bearbeiter']) ? $_POST['bearbeiter'] : null; - $type = $this->input->post('typeId'); - $start = $this->input->post('start'); - $ende = $this->input->post('ende'); + $titel = $post_data['titel']; + $text = $post_data['text']; + $erledigt = $post_data['erledigt']; + $bearbeiter_uid = isset($post_data['bearbeiter']) ? $post_data['bearbeiter'] : null; + $type = $post_data['typeId']; + $start = isset($post_data['start']) ? $post_data['start'] : null; + $ende = isset($post_data['ende']) ? $post_data['ende'] : null; // Start DB transaction $this->db->trans_start(); //Save note - $result = $this->NotizModel->insert(array('titel' => $titel, 'text' => $text, 'erledigt' => $erledigt, 'verfasser_uid' => $verfasser_uid, - "insertvon" => $verfasser_uid, 'start' => $start, 'ende' => $ende, 'bearbeiter_uid' => $bearbeiter_uid)); + $result = $this->NotizModel->insert(array('titel' => $titel, 'text' => $text, 'erledigt' => $erledigt, 'verfasser_uid' => $uid, + "insertvon" => $uid, 'start' => $start, 'ende' => $ende, 'bearbeiter_uid' => $bearbeiter_uid)); if (isError($result)) { $this->db->trans_rollback(); - return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); } $notiz_id = $result->retval; @@ -220,7 +213,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller if (isError($result)) { $this->db->trans_rollback(); - return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); } $dms_id_arr[] = $result->retval['dms_id']; } @@ -235,34 +228,28 @@ abstract class Notiz_Controller extends FHCAPI_Controller if (isError($result)) { $this->db->trans_rollback(); - return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); } } } $this->db->trans_commit(); - return $this->terminateWithSuccess($result); + $this->terminateWithSuccess($result); } public function updateNotiz() { + $this->load->library('form_validation'); $this->load->library('DmsLib'); - if (isset($_POST['data'])) - { - $data = json_decode($_POST['data']); - unset($_POST['data']); - foreach ($data as $k => $v) { - $_POST[$k] = $v; - } - } + $json = $this->input->post('data'); + $post_data = json_decode($json, true); - $notiz_id = $this->input->post('notiz_id'); + $this->form_validation->set_data($post_data); - if(!$notiz_id) - { - $this->terminateWithError($this->p->t('ui','error_missingId',['id'=>'Notiz_id']), self::ERROR_TYPE_GENERAL); - } + $this->form_validation->set_rules('notiz_id', 'Notiz ID', 'required', [ + 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'notiz_id']) + ]); //Form Validation $this->form_validation->set_rules('titel', 'Titel', 'required', [ @@ -280,25 +267,23 @@ abstract class Notiz_Controller extends FHCAPI_Controller //update Notiz $uid = getAuthUID(); - $titel = $this->input->post('titel'); - $text = $this->input->post('text'); - $verfasser_uid = isset($_POST['verfasser']) ? $_POST['verfasser'] : $uid; - $bearbeiter_uid = isset($_POST['bearbeiter']) ? $_POST['bearbeiter'] : $uid; - $erledigt = $this->input->post('erledigt'); - $start = $this->input->post('start'); - $ende = $this->input->post('ende'); + $titel = $post_data['titel']; + $text = $post_data['text']; + $bearbeiter_uid = isset($post_data['bearbeiter']) ? $post_data['bearbeiter'] : $post_data['bearbeiter_uid']; + $erledigt = $post_data['erledigt']; + $start = $post_data['start']; + $ende = $post_data['ende']; $result = $this->NotizModel->update( [ - 'notiz_id' => $notiz_id + 'notiz_id' => $post_data['notiz_id'], ], [ 'titel' => $titel, 'updatevon' => $uid, 'updateamum' => date('c'), 'text' => $text, - 'verfasser_uid' => $verfasser_uid, - 'bearbeiter_uid' => $bearbeiter_uid, + 'bearbeiter_uid' => isEmptyString($bearbeiter_uid) ? null : $bearbeiter_uid, 'start' => $start, 'ende' => $ende, 'erledigt' => $erledigt @@ -306,7 +291,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller ); if (isError($result)) { - return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); } //update(1) loading all dms-entries with this notiz_id @@ -314,7 +299,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller $this->load->model('person/Notizdokument_model', 'NotizdokumentModel'); $this->NotizdokumentModel->addJoin('campus.tbl_dms_version', 'dms_id'); - $result = $this->NotizdokumentModel->loadWhere(array('notiz_id' => $notiz_id)); + $result = $this->NotizdokumentModel->loadWhere(array('notiz_id' => $post_data['notiz_id'])); $result = $this->getDataOrTerminateWithError($result); foreach ($result as $doc) { $dms_id_arr[$doc->dms_id] = array( @@ -351,7 +336,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller $result = $this->getDataOrTerminateWithError($result); $dms_id = $result['dms_id']; - $result = $this->NotizdokumentModel->insert(array('notiz_id' => $notiz_id, 'dms_id' => $dms_id)); + $result = $this->NotizdokumentModel->insert(array('notiz_id' => $post_data['notiz_id'], 'dms_id' => $dms_id)); $this->getDataOrTerminateWithError($result); } @@ -365,7 +350,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller $this->getDataOrTerminateWithError($result); } - return $this->terminateWithSuccess($result); + $this->terminateWithSuccess($result); } public function deleteNotiz() @@ -416,15 +401,15 @@ abstract class Notiz_Controller extends FHCAPI_Controller if (isError($result)) { $this->db->trans_rollback(); - return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); } if(!hasData($result)) { - return $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL); + $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL); } $this->db->trans_complete(); - return $this->terminateWithSuccess(getData($result)); + $this->terminateWithSuccess(getData($result)); } public function loadDokumente() @@ -440,14 +425,14 @@ abstract class Notiz_Controller extends FHCAPI_Controller array('public.tbl_notiz.notiz_id' => $notiz_id) ); if (isError($result)) { - return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); + $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); } if(!hasData($result)) { - return $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL); + $this->terminateWithError($this->p->t('ui','error_missingId', ['id'=> 'Notiz_id']), self::ERROR_TYPE_GENERAL); } - return $this->terminateWithSuccess(getData($result)); + $this->terminateWithSuccess(getData($result)); } public function getMitarbeiter($searchString) @@ -457,7 +442,7 @@ abstract class Notiz_Controller extends FHCAPI_Controller if (isError($result)) { $this->terminateWithError($result, self::ERROR_TYPE_GENERAL); } - return $this->terminateWithSuccess($result); + $this->terminateWithSuccess($result); } public function getCountNotes($person_id) @@ -476,4 +461,4 @@ abstract class Notiz_Controller extends FHCAPI_Controller return $this->terminateWithSuccess($anzahl->anzahl ?: 0); } -} \ No newline at end of file +} diff --git a/application/views/Studentenverwaltung.php b/application/views/Studentenverwaltung.php index 1cd28d735..4f2311334 100644 --- a/application/views/Studentenverwaltung.php +++ b/application/views/Studentenverwaltung.php @@ -14,12 +14,14 @@ 'ui', 'notiz', ), + 'tags' => true, 'customCSSs' => [ #datepicker fuer component functions 'public/css/components/vue-datepicker.css', 'public/css/components/primevue.css', 'public/css/Studentenverwaltung.css', - 'public/css/components/function.css' + 'public/css/components/function.css', + //'public/css/Lvverwaltung.css' //css tags? ], 'customJSs' => [ 'vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js', diff --git a/public/js/api/factory/notiz/anrechnung.js b/public/js/api/factory/notiz/anrechnung.js new file mode 100644 index 000000000..ba458abf5 --- /dev/null +++ b/public/js/api/factory/notiz/anrechnung.js @@ -0,0 +1,29 @@ +/** + * 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 . + */ + +import Person from './person.js'; + +export default { + + ...Person, + getNotizen(id, type) { + return { + method: 'get', + url: 'api/frontend/v1/notiz/notizAnrechnung/getNotizen/' + encodeURIComponent(id) + '/' + encodeURIComponent(type) + }; + }, +}; diff --git a/public/js/api/factory/notiz/bestellung.js b/public/js/api/factory/notiz/bestellung.js new file mode 100644 index 000000000..3d94a7c25 --- /dev/null +++ b/public/js/api/factory/notiz/bestellung.js @@ -0,0 +1,29 @@ +/** + * 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 . + */ + +import Person from './person.js'; + +export default { + + ...Person, + getNotizen(id, type) { + return { + method: 'get', + url: 'api/frontend/v1/notiz/notizBestellung/getNotizen/' + encodeURIComponent(id) + '/' + encodeURIComponent(type) + }; + }, +}; \ No newline at end of file diff --git a/public/js/api/factory/notiz/lehreinheit.js b/public/js/api/factory/notiz/lehreinheit.js index d93bb50f9..762e5c596 100644 --- a/public/js/api/factory/notiz/lehreinheit.js +++ b/public/js/api/factory/notiz/lehreinheit.js @@ -26,4 +26,29 @@ export default { url: 'api/frontend/v1/notiz/notizLehreinheit/getNotizen/' + encodeURIComponent(id) + '/' + encodeURIComponent(type) }; }, + addNewNotiz(lehreinheit_id, params) { + return { + method: 'post', + url: 'api/frontend/v1/notiz/notizLehreinheit/addNewNotiz/' + lehreinheit_id, + params + }; + }, + updateNotiz(notiz_id, params) { + return { + method: 'post', + url: 'api/frontend/v1/notiz/notizLehreinheit/updateNotiz/' + notiz_id, + params + }; + }, + deleteNotiz(notiz_id, type_id, id) { + return { + method: 'post', + url: 'api/frontend/v1/notiz/notizLehreinheit/deleteNotiz/', + params: { + notiz_id, + type_id, + id + } + }; + }, }; diff --git a/public/js/api/factory/notiz/mitarbeiter.js b/public/js/api/factory/notiz/mitarbeiter.js new file mode 100644 index 000000000..6ddb89af7 --- /dev/null +++ b/public/js/api/factory/notiz/mitarbeiter.js @@ -0,0 +1,29 @@ +/** + * 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 . + */ + +import Person from './person.js'; + +export default { + + ...Person, + getNotizen(id, type) { + return { + method: 'get', + url: 'api/frontend/v1/notiz/notizMitarbeiter/getNotizen/' + encodeURIComponent(id) + '/' + encodeURIComponent(type) + }; + }, +}; \ No newline at end of file diff --git a/public/js/api/factory/notiz/prestudent.js b/public/js/api/factory/notiz/prestudent.js new file mode 100644 index 000000000..f117a77ff --- /dev/null +++ b/public/js/api/factory/notiz/prestudent.js @@ -0,0 +1,29 @@ +/** + * 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 . + */ + +import Person from './person.js'; + +export default { + + ...Person, + getNotizen(id, type) { + return { + method: 'get', + url: 'api/frontend/v1/notiz/notizPrestudent/getNotizen/' + encodeURIComponent(id) + '/' + encodeURIComponent(type) + }; + }, +}; \ No newline at end of file diff --git a/public/js/api/factory/notiz/projekt.js b/public/js/api/factory/notiz/projekt.js new file mode 100644 index 000000000..f1dab754d --- /dev/null +++ b/public/js/api/factory/notiz/projekt.js @@ -0,0 +1,29 @@ +/** + * 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 . + */ + +import Person from './person.js'; + +export default { + + ...Person, + getNotizen(id, type) { + return { + method: 'get', + url: 'api/frontend/v1/notiz/notizProjekt/getNotizen/' + encodeURIComponent(id) + '/' + encodeURIComponent(type) + }; + }, +}; \ No newline at end of file diff --git a/public/js/api/factory/notiz/projektphase.js b/public/js/api/factory/notiz/projektphase.js new file mode 100644 index 000000000..6762e8456 --- /dev/null +++ b/public/js/api/factory/notiz/projektphase.js @@ -0,0 +1,29 @@ +/** + * 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 . + */ + +import Person from './person.js'; + +export default { + + ...Person, + getNotizen(id, type) { + return { + method: 'get', + url: 'api/frontend/v1/notiz/notizProjektphase/getNotizen/' + encodeURIComponent(id) + '/' + encodeURIComponent(type) + }; + }, +}; \ No newline at end of file diff --git a/public/js/api/factory/notiz/projekttask.js b/public/js/api/factory/notiz/projekttask.js new file mode 100644 index 000000000..27a74bb08 --- /dev/null +++ b/public/js/api/factory/notiz/projekttask.js @@ -0,0 +1,29 @@ +/** + * 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 . + */ + +import Person from './person.js'; + +export default { + + ...Person, + getNotizen(id, type) { + return { + method: 'get', + url: 'api/frontend/v1/notiz/notizProjekttask/getNotizen/' + encodeURIComponent(id) + '/' + encodeURIComponent(type) + }; + }, +}; \ No newline at end of file diff --git a/public/js/api/factory/stv/tag.js b/public/js/api/factory/stv/tag.js new file mode 100644 index 000000000..29675f6d4 --- /dev/null +++ b/public/js/api/factory/stv/tag.js @@ -0,0 +1,54 @@ +export default { + + getTag(data) + { + return { + method: 'get', + url: 'api/frontend/v1/stv/Tags/getTag', + params: data + }; + }, + + getTags(data) + { + return { + method: 'get', + url: 'api/frontend/v1/stv/Tags/getTags' + }; + }, + + addTag(data) + { + return { + method: 'post', + url: 'api/frontend/v1/stv/Tags/addTag', + params: data + }; + }, + + updateTag(data) + { + return { + method: 'post', + url: 'api/frontend/v1/stv/Tags/updateTag', + params: data + }; + }, + doneTag(data) + { + return { + method: 'post', + url: 'api/frontend/v1/stv/Tags/doneTag', + params: data + }; + }, + + deleteTag(data) + { + return { + method: 'post', + url: 'api/frontend/v1/stv/Tags/deleteTag', + params: data + }; + }, +}; \ No newline at end of file diff --git a/public/js/api/notiz.js b/public/js/api/notiz.js index 0a1034703..a75eb6f2d 100644 --- a/public/js/api/notiz.js +++ b/public/js/api/notiz.js @@ -1,5 +1,22 @@ import person from "./notiz/person.js"; +import prestudent from "./notiz/prestudent.js"; +import mitarbeiter from "./notiz/mitarbeiter.js"; +import projekt from "./notiz/projekt.js"; +import anrechnung from "./notiz/anrechnung.js"; +import bestellung from "./notiz/bestellung.js"; +import lehreinheit from "./notiz/lehreinheit.js"; +import projektphase from "./notiz/projektphase.js"; +import projekttask from "./notiz/projekttask.js"; + export default { - person -} \ No newline at end of file + person, + prestudent, + mitarbeiter, + anrechnung, + bestellung, + lehreinheit, + projekt, + projektphase, + projekttask, +} diff --git a/public/js/api/notiz/anrechnung.js b/public/js/api/notiz/anrechnung.js new file mode 100644 index 000000000..843017687 --- /dev/null +++ b/public/js/api/notiz/anrechnung.js @@ -0,0 +1,38 @@ +export default { + getNotizen(url, config, params){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizAnrechnung/getNotizen/' + params.id + '/' + params.type); + }, + getUid(){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizAnrechnung/getUid/'); + }, + addNewNotiz(id, formData) { + return this.$fhcApi.post('api/frontend/v1/notiz/notizAnrechnung/addNewNotiz/' + id, + formData + ); + }, + loadNotiz(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizAnrechnung/loadNotiz/', { + notiz_id + }); + }, + loadDokumente(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizAnrechnung/loadDokumente/', { + notiz_id + }); + }, + deleteNotiz(notiz_id, type_id, id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizAnrechnung/deleteNotiz/', { + notiz_id, + type_id, + id + }); + }, + updateNotiz(notiz_id, formData){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizAnrechnung/updateNotiz/' + notiz_id, + formData + ); + }, + getMitarbeiter(event){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizAnrechnung/getMitarbeiter/' + event); + } +} \ No newline at end of file diff --git a/public/js/api/notiz/bestellung.js b/public/js/api/notiz/bestellung.js new file mode 100644 index 000000000..3f0f5268c --- /dev/null +++ b/public/js/api/notiz/bestellung.js @@ -0,0 +1,38 @@ +export default { + getNotizen(url, config, params){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizBestellung/getNotizen/' + params.id + '/' + params.type); + }, + getUid(){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizBestellung/getUid/'); + }, + addNewNotiz(id, formData) { + return this.$fhcApi.post('api/frontend/v1/notiz/notizBestellung/addNewNotiz/' + id, + formData + ); + }, + loadNotiz(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizBestellung/loadNotiz/', { + notiz_id + }); + }, + loadDokumente(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizBestellung/loadDokumente/', { + notiz_id + }); + }, + deleteNotiz(notiz_id, type_id, id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizBestellung/deleteNotiz/', { + notiz_id, + type_id, + id + }); + }, + updateNotiz(notiz_id, formData){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizBestellung/updateNotiz/' + notiz_id, + formData + ); + }, + getMitarbeiter(event){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizBestellung/getMitarbeiter/' + event); + } +} \ No newline at end of file diff --git a/public/js/api/notiz/lehreinheit.js b/public/js/api/notiz/lehreinheit.js new file mode 100644 index 000000000..85b3187ae --- /dev/null +++ b/public/js/api/notiz/lehreinheit.js @@ -0,0 +1,38 @@ +export default { + getNotizen(url, config, params){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizLehreinheit/getNotizen/' + params.id + '/' + params.type); + }, + getUid(){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizLehreinheit/getUid/'); + }, + addNewNotiz(id, formData) { + return this.$fhcApi.post('api/frontend/v1/notiz/notizLehreinheit/addNewNotiz/' + id, + formData + ); + }, + loadNotiz(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizLehreinheit/loadNotiz/', { + notiz_id + }); + }, + loadDokumente(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizLehreinheit/loadDokumente/', { + notiz_id + }); + }, + deleteNotiz(notiz_id, type_id, id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizLehreinheit/deleteNotiz/', { + notiz_id, + type_id, + id + }); + }, + updateNotiz(notiz_id, formData){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizLehreinheit/updateNotiz/' + notiz_id, + formData + ); + }, + getMitarbeiter(event){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizLehreinheit/getMitarbeiter/' + event); + } +} \ No newline at end of file diff --git a/public/js/api/notiz/mitarbeiter.js b/public/js/api/notiz/mitarbeiter.js new file mode 100644 index 000000000..ada9b0ae8 --- /dev/null +++ b/public/js/api/notiz/mitarbeiter.js @@ -0,0 +1,38 @@ +export default { + getNotizen(url, config, params){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizMitarbeiter/getNotizen/' + params.id + '/' + params.type); + }, + getUid(){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizMitarbeiter/getUid/'); + }, + addNewNotiz(id, formData) { + return this.$fhcApi.post('api/frontend/v1/notiz/notizMitarbeiter/addNewNotiz/' + id, + formData + ); + }, + loadNotiz(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizMitarbeiter/loadNotiz/', { + notiz_id + }); + }, + loadDokumente(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizMitarbeiter/loadDokumente/', { + notiz_id + }); + }, + deleteNotiz(notiz_id, type_id, id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizMitarbeiter/deleteNotiz/', { + notiz_id, + type_id, + id + }); + }, + updateNotiz(notiz_id, formData){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizMitarbeiter/updateNotiz/' + notiz_id, + formData + ); + }, + getMitarbeiter(event){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizMitarbeiter/getMitarbeiter/' + event); + } +} \ No newline at end of file diff --git a/public/js/api/notiz/person.js b/public/js/api/notiz/person.js index 04812eacc..cce0ff8c0 100644 --- a/public/js/api/notiz/person.js +++ b/public/js/api/notiz/person.js @@ -38,4 +38,4 @@ export default { isBerechtigt(id, type_id){ return this.$fhcApi.get('api/frontend/v1/notiz/notizPerson/isBerechtigt/'); } -} \ No newline at end of file +} diff --git a/public/js/api/notiz/prestudent.js b/public/js/api/notiz/prestudent.js new file mode 100644 index 000000000..c529ea44e --- /dev/null +++ b/public/js/api/notiz/prestudent.js @@ -0,0 +1,38 @@ +export default { + getNotizen(url, config, params){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizPrestudent/getNotizen/' + params.id + '/' + params.type); + }, + getUid(){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizPrestudent/getUid/'); + }, + addNewNotiz(id, formData) { + return this.$fhcApi.post('api/frontend/v1/notiz/notizPrestudent/addNewNotiz/' + id, + formData + ); + }, + loadNotiz(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizPrestudent/loadNotiz/', { + notiz_id + }); + }, + loadDokumente(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizPrestudent/loadDokumente/', { + notiz_id + }); + }, + deleteNotiz(notiz_id, type_id, id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizPrestudent/deleteNotiz/', { + notiz_id, + type_id, + id + }); + }, + updateNotiz(notiz_id, formData){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizPrestudent/updateNotiz/' + notiz_id, + formData + ); + }, + getMitarbeiter(event){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizPrestudent/getMitarbeiter/' + event); + } +} \ No newline at end of file diff --git a/public/js/api/notiz/projekt.js b/public/js/api/notiz/projekt.js new file mode 100644 index 000000000..ac8b71623 --- /dev/null +++ b/public/js/api/notiz/projekt.js @@ -0,0 +1,38 @@ +export default { + getNotizen(url, config, params){ + return this.$fhcApi.get('api/frontend/v1/notiz/NotizProjekt/getNotizen/' + params.id + '/' + params.type); + }, + getUid(){ + return this.$fhcApi.get('api/frontend/v1/notiz/NotizProjekt/getUid/'); + }, + addNewNotiz(id, formData) { + return this.$fhcApi.post('api/frontend/v1/notiz/NotizProjekt/addNewNotiz/' + id, + formData + ); + }, + loadNotiz(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/NotizProjekt/loadNotiz/', { + notiz_id + }); + }, + loadDokumente(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/NotizProjekt/loadDokumente/', { + notiz_id + }); + }, + deleteNotiz(notiz_id, type_id, id){ + return this.$fhcApi.post('api/frontend/v1/notiz/NotizProjekt/deleteNotiz/', { + notiz_id, + type_id, + id + }); + }, + updateNotiz(notiz_id, formData){ + return this.$fhcApi.post('api/frontend/v1/notiz/NotizProjekt/updateNotiz/' + notiz_id, + formData + ); + }, + getMitarbeiter(event){ + return this.$fhcApi.get('api/frontend/v1/notiz/NotizProjekt/getMitarbeiter/' + event); + } +} \ No newline at end of file diff --git a/public/js/api/notiz/projektphase.js b/public/js/api/notiz/projektphase.js new file mode 100644 index 000000000..8b85106a3 --- /dev/null +++ b/public/js/api/notiz/projektphase.js @@ -0,0 +1,38 @@ +export default { + getNotizen(url, config, params){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizProjektphase/getNotizen/' + params.id + '/' + params.type); + }, + getUid(){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizProjektphase/getUid/'); + }, + addNewNotiz(id, formData) { + return this.$fhcApi.post('api/frontend/v1/notiz/notizProjektphase/addNewNotiz/' + id, + formData + ); + }, + loadNotiz(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizProjektphase/loadNotiz/', { + notiz_id + }); + }, + loadDokumente(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizProjektphase/loadDokumente/', { + notiz_id + }); + }, + deleteNotiz(notiz_id, type_id, id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizProjektphase/deleteNotiz/', { + notiz_id, + type_id, + id + }); + }, + updateNotiz(notiz_id, formData){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizProjektphase/updateNotiz/' + notiz_id, + formData + ); + }, + getMitarbeiter(event){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizProjektphase/getMitarbeiter/' + event); + } +} \ No newline at end of file diff --git a/public/js/api/notiz/projekttask.js b/public/js/api/notiz/projekttask.js new file mode 100644 index 000000000..6b6db3c77 --- /dev/null +++ b/public/js/api/notiz/projekttask.js @@ -0,0 +1,38 @@ +export default { + getNotizen(url, config, params){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizProjekttask/getNotizen/' + params.id + '/' + params.type); + }, + getUid(){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizProjekttask/getUid/'); + }, + addNewNotiz(id, formData) { + return this.$fhcApi.post('api/frontend/v1/notiz/notizProjekttask/addNewNotiz/' + id, + formData + ); + }, + loadNotiz(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizProjekttask/loadNotiz/', { + notiz_id + }); + }, + loadDokumente(notiz_id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizProjekttask/loadDokumente/', { + notiz_id + }); + }, + deleteNotiz(notiz_id, type_id, id){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizProjekttask/deleteNotiz/', { + notiz_id, + type_id, + id + }); + }, + updateNotiz(notiz_id, formData){ + return this.$fhcApi.post('api/frontend/v1/notiz/notizProjekttask/updateNotiz/' + notiz_id, + formData + ); + }, + getMitarbeiter(event){ + return this.$fhcApi.get('api/frontend/v1/notiz/notizProjekttask/getMitarbeiter/' + event); + } +} \ No newline at end of file diff --git a/public/js/components/LVVerwaltung/Setup/Table.js b/public/js/components/LVVerwaltung/Setup/Table.js index 830cfc9ea..67c63c3bb 100644 --- a/public/js/components/LVVerwaltung/Setup/Table.js +++ b/public/js/components/LVVerwaltung/Setup/Table.js @@ -4,6 +4,8 @@ import DetailsForm from "../Details/Form.js"; import CoreTag from '../../Tag/Tag.js'; import { tagHeaderFilter } from '../../../../js/tabulator/filters/extendedHeaderFilter.js'; import { extendedHeaderFilter } from "../../../../js/tabulator/filters/extendedHeaderFilter.js"; +import { tagFormatter } from "../../../../js/tabulator/formatter/tags.js"; +import { addTagInTable, deleteTagInTable, updateTagInTable } from "../../../../js/helpers/TagHelper.js"; import ApiLv from "../../../api/lehrveranstaltung.js"; import ApiTag from "../../../api/lehrveranstaltung/tag.js"; @@ -223,72 +225,7 @@ export default { headerFilter: "input", headerFilterFunc: tagHeaderFilter, headerFilterFuncParams: {field: 'tags'}, - formatter: (cell) => { - let tags = cell.getValue(); - if (!tags) return; - - let container = document.createElement('div'); - container.className = "d-flex gap-1"; - - let parsedTags = JSON.parse(tags); - let maxVisibleTags = 2; - - const rowData = cell.getRow().getData(); - if (rowData._tagExpanded === undefined) { - rowData._tagExpanded = false; - } - - const renderTags = () => { - container.innerHTML = ''; - parsedTags = parsedTags.filter(item => item !== null); - - parsedTags.sort((a, b) => { - let adone = a.done ? 1 : 0; - let bbone = b.done ? 1 : 0; - - if (adone !== bbone) - { - return adone - bbone; - } - return b.id - a.id; - }); - const tagsToShow = rowData._tagExpanded ? parsedTags : parsedTags.slice(0, maxVisibleTags); - - tagsToShow.forEach(tag => { - if (!tag) return; - let tagElement = document.createElement('span'); - tagElement.innerText = tag.beschreibung; - tagElement.title = tag.notiz; - tagElement.className = "tag " + tag.style; - if (tag.done) tagElement.className += " tag_done"; - - tagElement.addEventListener('click', (event) => { - event.stopPropagation(); - event.preventDefault(); - this.$refs.tagComponent.editTag(tag.id); - }); - - container.appendChild(tagElement); - }); - - if (parsedTags.length > maxVisibleTags) { - let toggle = document.createElement('button'); - toggle.innerText = (rowData._tagExpanded ? '- ' : '+ ') + (parsedTags.length - maxVisibleTags); - toggle.className = "display_all"; - toggle.title = rowData._tagExpanded ? "Tags ausblenden" : "Tags einblenden"; - - toggle.addEventListener('click', () => { - rowData._tagExpanded = !rowData._tagExpanded; - renderTags(); - }); - - container.appendChild(toggle); - } - }; - - renderTags(); - return container; - }, + formatter: (cell) => tagFormatter(cell, this.$refs.tagComponent), width: 150, }, { @@ -444,104 +381,16 @@ export default { }, addedTag(addedTag) { - const table = this.$refs.table.tabulator; - - this.selectedRows.forEach(row => - { - if (Array.isArray(addedTag.response)) - { - addedTag.response.forEach(tag => { - const targetRow = this.allRows.find(row => row.getData().lehreinheit_id === tag.lehreinheit_id); - if (targetRow) - { - const rowData = targetRow.getData(); - let tags = []; - try { - tags = JSON.parse(rowData.tags || '[]'); - } catch (e) {} - - const tagExists = tags.some((t) => t.id === tag.id); - if (!tagExists) - { - addedTag.id = tag.id; - tags.unshift({ ...addedTag }); - targetRow.update({ tags: JSON.stringify(tags) }); - targetRow.reformat(); - } - } - }); - } - }); + addTagInTable(addedTag, this.allRows, 'lehreinheit_id') }, - deletedTag(deletedTag) { - const targetRow = this.allRows.find(row => { - const rowData = row.getData(); - - let tags = []; - try { - tags = JSON.parse(rowData.tags || '[]'); - } catch (e) {} - - return tags.some(tag => tag.id === deletedTag); - }); - - if (targetRow) { - const rowData = targetRow.getData(); - let tags = []; - - try { - tags = JSON.parse(rowData.tags || '[]'); - } catch (e) {} - - const filteredTags = tags.filter(t => t.id !== deletedTag); - const updatedTags = JSON.stringify(filteredTags); - - if (updatedTags !== rowData.tags) { - targetRow.update({ - tags: updatedTags - }); - - targetRow.reformat(); - } - } + deletedTag(deletedTag) + { + deleteTagInTable(deletedTag, this.allRows); }, - updatedTag(updatedTag) { - const targetRow = this.allRows.find(row => { - const rowData = row.getData(); - let tags = []; - - try { - tags = JSON.parse(rowData.tags || '[]'); - } catch (e) {} - - return tags.some(t => t?.id === updatedTag.id); - }); - - if (targetRow) - { - const rowData = targetRow.getData(); - let tags = []; - try { - tags = JSON.parse(rowData.tags || '[]'); - } catch (e) {} - - let changed = false; - - const tagIndex = tags.findIndex(tag => tag?.id === updatedTag.id); - if (tagIndex !== -1) { - tags[tagIndex] = { ...updatedTag }; - changed = true; - } - - if (changed) - { - targetRow.update({ - tags: JSON.stringify(tags), - }); - targetRow.reformat(); - } - } + updatedTag(updatedTag) + { + updateTagInTable(updatedTag, this.allRows); }, async copyLehreinheit(row, art) { diff --git a/public/js/components/Notiz/Notiz.js b/public/js/components/Notiz/Notiz.js index 39f0e507e..e08f3e019 100644 --- a/public/js/components/Notiz/Notiz.js +++ b/public/js/components/Notiz/Notiz.js @@ -1,5 +1,4 @@ import VueDatePicker from '../vueDatepicker.js.php'; -import PvAutoComplete from "../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"; import FormUploadDms from '../Form/Upload/Dms.js'; import {CoreFilterCmpt} from "../filter/Filter.js"; import BsModal from "../Bootstrap/Modal.js"; @@ -11,7 +10,6 @@ export default { components: { CoreFilterCmpt, VueDatePicker, - PvAutoComplete, FormUploadDms, FormForm, FormInput, @@ -281,6 +279,7 @@ export default { editor: null, notizData: { typeId: this.typeId, + id: this.id, titel: null, statusNew: true, text: '', @@ -307,7 +306,8 @@ export default { showType_id: false, showId: false, showLastupdate: false - } + }, + currentVerfasserUid: null } }, methods: { @@ -335,8 +335,6 @@ export default { this.notizData.bis = this.notizen.ende; this.notizData.document = this.notizen.dms_id; this.notizData.erledigt = this.notizen.erledigt; - this.notizData.verfasser = this.notizen.verfasser_uid; - this.notizData.intVerfasser = this.notizen.verfasser_uid; this.notizData.intBearbeiter = this.notizen.bearbeiter_uid; this.notizData.bearbeiter = this.notizen.bearbeiter_uid; } @@ -359,6 +357,7 @@ export default { }, addNewNotiz() { const formData = new FormData(); + this.notizData.id = this.id; formData.append('data', JSON.stringify(this.notizData)); Object.entries(this.notizData.anhang).forEach(([k, v]) => formData.append(k, v)); @@ -402,6 +401,7 @@ export default { this.notizData = result.data; this.notizData.typeId = this.typeId; this.notizData.anhang = []; + this.currentVerfasserUid = result.data.verfasser_uid; return result; }) .catch(this.$fhcAlert.handleSystemError); @@ -455,16 +455,17 @@ export default { bis: null, document: null, erledigt: false, - verfasser: this.uid, bearbeiter: null, - anhang: [] + anhang: [], }; + this.currentVerfasserUid = this.uid }, getUid() { return this.$api .call(this.endpoint.getUid()) .then(result => { - this.notizData.intVerfasser = result.data; + this.currentVerfasserUid = result.data; + this.uid = result.data; }) .catch(this.$fhcAlert.handleSystemError); }, @@ -547,14 +548,7 @@ export default { }, deep: true }, - 'notizData.intVerfasser': { - handler(newVal) { - if (typeof newVal === 'object') { - this.notizData.verfasser = newVal.mitarbeiter_uid; - } - }, - deep: true - }, + id() { this.reload(); } @@ -654,24 +648,23 @@ export default {
-
- -
-
- +
+
- + > +
@@ -679,26 +672,35 @@ export default {
- +
- + +
- - + > +
@@ -842,28 +844,15 @@ export default {
- - - - + - - - @@ -1195,33 +1171,21 @@ export default {
- - - - + @@ -1235,6 +1199,7 @@ export default { :suggestions="filteredMitarbeiter" @complete="search" optionLabel="mitarbeiter" + name="bearbeiter" minlength="3" > @@ -1292,4 +1257,4 @@ export default {

Kein Layout übergeben

`, -} \ No newline at end of file +} diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Notizen.js b/public/js/components/Stv/Studentenverwaltung/Details/Notizen.js index a28f21e62..77eb8adba 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Notizen.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Notizen.js @@ -17,7 +17,6 @@ export default { }, template: `
- - --> + +-->
` -}; \ No newline at end of file +}; diff --git a/public/js/components/Stv/Studentenverwaltung/List.js b/public/js/components/Stv/Studentenverwaltung/List.js index 045326ae6..3188c61d7 100644 --- a/public/js/components/Stv/Studentenverwaltung/List.js +++ b/public/js/components/Stv/Studentenverwaltung/List.js @@ -1,5 +1,11 @@ import {CoreFilterCmpt} from "../../filter/Filter.js"; import ListNew from './List/New.js'; +import CoreTag from '../../Tag/Tag.js'; +import { tagHeaderFilter } from "../../../tabulator/filters/extendedHeaderFilter.js"; +import { addTagInTable, deleteTagInTable, updateTagInTable } from "../../../../js/helpers/TagHelper.js"; +import { tagFormatter } from "../../../../js/tabulator/formatter/tags.js"; +//import { extendedHeaderFilter } from "../../../tabulator/filters/extendedHeaderFilter.js"; +import ApiTag from "../../../api/factory/stv/tag.js"; import ListFilter from './List/Filter.js'; import { capitalize } from '../../../helpers/StringHelpers.js'; @@ -11,6 +17,7 @@ export default { components: { CoreFilterCmpt, ListNew, + CoreTag, ListFilter }, directives: { @@ -57,6 +64,16 @@ export default { columns:[ {title:"UID", field:"uid", headerFilter: true}, {title:"TitelPre", field:"titelpre", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}}, + { + title: 'Tags', + field: 'tags', + tooltip: false, + headerFilter: "input", + headerFilterFunc: tagHeaderFilter, + headerFilterFuncParams: {field: 'tags'}, + formatter: (cell) => tagFormatter(cell, this.$refs.tagComponent), + width: 150, + }, {title:"Nachname", field:"nachname", headerFilter: true}, {title:"Vorname", field:"vorname", headerFilter: true}, {title:"Wahlname", field:"wahlname", visible:false, headerFilter: true}, @@ -157,7 +174,7 @@ export default { selectable: true, selectableRangeMode: 'click', index: 'prestudent_id', - persistenceID: 'stv-list' + persistenceID: 'stv-list', }, tabulatorEvents: [ { @@ -166,7 +183,10 @@ export default { }, { event: 'dataProcessed', - handler: this.autoSelectRows + handler: (data) => { + this.getAllRows() + this.autoSelectRows(data) + } }, { event: 'dataLoaded', @@ -179,6 +199,18 @@ export default { { event: 'rowClick', handler: this.handleRowClick // TODO(chris): this should be in the filter component + }, + { + event: 'dataTreeRowExpanded', + handler: (data) => { + this.getExpandedRows() + } + }, + { + event: 'dataTreeRowCollapsed', + handler: (data) => { + this.getExpandedRows() + } } ], focusObj: null, // TODO(chris): this should be in the filter component @@ -187,6 +219,10 @@ export default { count: 0, filteredcount: 0, selectedcount: 0, + //tags + expanded: [], + selectedColumnValues: [], + tagEndpoint: ApiTag, currentEndpoint: null } }, @@ -327,6 +363,11 @@ export default { rowSelectionChanged(data, rows) { this.selectedcount = data.length; this.lastSelected = this.selected; + + //for tags + this.selectedRows = this.$refs.table.tabulator.getSelectedRows(); + this.selectedColumnValues = this.selectedRows.filter(row => row.getData().prestudent_id !== undefined && row.getData().prestudent_id).map(row => row.getData().prestudent_id); + this.$emit('update:selected', data); // set selected elements draggable @@ -339,7 +380,7 @@ export default { rows.forEach(row => row.getElement().draggable = true); }, autoSelectRows(data) { - if (this.lastSelected) { + if (Array.isArray(this.lastSelected) && this.lastSelected.length){ // NOTE(chris): reselect rows on refresh let selected = this.lastSelected.map(el => this.$refs.table.tabulator.getRow(el.prestudent_id)) // TODO(chris): unselect current item if it's no longer in the table? @@ -348,7 +389,7 @@ export default { if (selected.length) this.$refs.table.tabulator.selectRow(selected); - } else if(this.lastSelected === undefined) { + } else if(data && this.lastSelected === undefined) { // NOTE(chris): select row if it's the only one (preferably only on startup) if (data.length == 1) { this.$refs.table.tabulator.selectRow(this.$refs.table.tabulator.getRows()); @@ -471,7 +512,24 @@ export default { if (el != this.focusObj) this.changeFocus(this.focusObj, el); } - } + }, + //methods tags + addedTag(addedTag) + { + addTagInTable(addedTag, this.allRows, 'prestudent_id') + }, + deletedTag(deletedTag) + { + deleteTagInTable(deletedTag, this.allRows); + }, + updatedTag(updatedTag) + { + updateTagInTable(updatedTag, this.allRows) + }, + getAllRows() { + this.allRows = this.$refs.table.tabulator.getRows(); + }, + }, // TODO(chris): focusin, focusout, keydown and tabindex should be in the filter component // TODO(chris): filter component column chooser has no accessibilty features @@ -500,6 +558,18 @@ export default { @click:new="actionNewPrestudent" @table-built="translateTabulator" > + + + `, -} \ No newline at end of file +} diff --git a/public/js/helpers/TagHelper.js b/public/js/helpers/TagHelper.js new file mode 100644 index 000000000..9282aa167 --- /dev/null +++ b/public/js/helpers/TagHelper.js @@ -0,0 +1,124 @@ +export function addTagInTable(addedTag, rows, matchKey, tagsKey = "tags") +{ + if (!addedTag || !Array.isArray(addedTag.response)) + return; + + rows.forEach(row => + { + const rowData = row.getData(); + let updated = false; + + addedTag.response.forEach(tag => + { + if (rowData[matchKey] !== tag[matchKey]) + return; + + let tags; + try { + tags = JSON.parse(rowData[tagsKey] || "[]"); + } catch (e) { + tags = []; + } + + if (!Array.isArray(tags)) + tags = []; + + if (tags.some(t => t?.id === tag.id)) + return; + + let newTag = { ...addedTag, id: tag.id }; + + tags.unshift(newTag); + + rowData[tagsKey] = JSON.stringify(tags); + updated = true; + }); + + if (updated) + row.update(rowData); + }); +} + +export function deleteTagInTable(deletedTag, rows, tagsKeys = ['tags']) +{ + if (!Array.isArray(tagsKeys)) + tagsKeys = [tagsKeys]; + + rows.forEach(row => { + let rowData = row.getData(); + let updates = {}; + let changed = false; + + tagsKeys.forEach(key => { + let tags; + + try { + tags = JSON.parse(rowData[key] || "[]"); + } catch (e) { + tags = []; + } + + if (!Array.isArray(tags)) + return; + + let filtered = tags.filter(tag => tag?.id !== deletedTag); + + if (filtered.length !== tags.length) + { + updates[key] = JSON.stringify(filtered); + changed = true; + } + }); + + if (changed) { + row.update(updates); + row.reformat(); + } + }); +} + + +export function updateTagInTable(updatedTag, rows, fields = ['tags']) +{ + if (!Array.isArray(fields)) + fields = [fields]; + + rows.forEach(row => + { + const rowData = row.getData(); + let updated = false; + + fields.forEach(field => + { + if (!rowData[field]) + return; + + let fieldData; + try { + fieldData = JSON.parse(rowData[field] || "[]"); + } catch (e) { + return; + } + + if (!Array.isArray(fieldData)) + return; + + let index = fieldData.findIndex(tag => tag?.id === updatedTag.id); + + if (index !== -1) + { + fieldData[index] = { ...updatedTag }; + let updatedFieldData = JSON.stringify(fieldData); + + if (updatedFieldData !== rowData[field]) + { + rowData[field] = updatedFieldData; + updated = true; + } + } + }); + + if (updated) + row.update(rowData); + }); +} diff --git a/public/js/tabulator/filters/extendedHeaderFilter.js b/public/js/tabulator/filters/extendedHeaderFilter.js index 7bf86c119..35b66dc1c 100644 --- a/public/js/tabulator/filters/extendedHeaderFilter.js +++ b/public/js/tabulator/filters/extendedHeaderFilter.js @@ -146,7 +146,7 @@ export function tagHeaderFilter(headerValue, rowValue, rowData, filterParams) if (Array.isArray(data)) { combinedText = data - .filter(item => item?.done === false) + .filter(item => item?.done !== true) .map(item => `${item?.beschreibung} ${item?.notiz}`) .join(' '); } diff --git a/public/js/tabulator/formatter/tags.js b/public/js/tabulator/formatter/tags.js new file mode 100644 index 000000000..0d2f5004c --- /dev/null +++ b/public/js/tabulator/formatter/tags.js @@ -0,0 +1,67 @@ +export function tagFormatter(cell, tagComponent) +{ + let tags = cell.getValue(); + if (!tags) return; + + let container = document.createElement('div'); + container.className = "d-flex gap-1"; + + let parsedTags = JSON.parse(tags); + let maxVisibleTags = 2; + + const rowData = cell.getRow().getData(); + if (rowData._tagExpanded === undefined) { + rowData._tagExpanded = false; + } + + const renderTags = () => { + container.innerHTML = ''; + parsedTags = parsedTags.filter(item => item !== null); + + parsedTags.sort((a, b) => { + let adone = a.done ? 1 : 0; + let bbone = b.done ? 1 : 0; + + if (adone !== bbone) + { + return adone - bbone; + } + return b.id - a.id; + }); + const tagsToShow = rowData._tagExpanded ? parsedTags : parsedTags.slice(0, maxVisibleTags); + + tagsToShow.forEach(tag => { + if (!tag) return; + let tagElement = document.createElement('span'); + tagElement.innerText = tag.beschreibung; + tagElement.title = tag.notiz; + tagElement.className = "tag " + tag.style; + if (tag.done) tagElement.className += " tag_done"; + + tagElement.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); + tagComponent.editTag(tag.id); + }); + + container.appendChild(tagElement); + }); + + if (parsedTags.length > maxVisibleTags) { + let toggle = document.createElement('button'); + toggle.innerText = (rowData._tagExpanded ? '- ' : '+ ') + (parsedTags.length - maxVisibleTags); + toggle.className = "display_all"; + toggle.title = rowData._tagExpanded ? "Tags ausblenden" : "Tags einblenden"; + + toggle.addEventListener('click', () => { + rowData._tagExpanded = !rowData._tagExpanded; + renderTags(); + }); + + container.appendChild(toggle); + } + }; + + renderTags(); + return container; +} \ No newline at end of file diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 4e8e844dd..b11ecc214 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -26071,6 +26071,27 @@ array( ) ) ), + //**************************** FHC-Core-Notizcomponent + array( + 'app' => 'core', + 'category' => 'ui', + 'phrase' => 'error_typeNotizIdIncorrect', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Id-Typ der Notiz ist nicht korrekt', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Id type of note is incorrect', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), array( 'app' => 'core', 'category' => 'ui',