From d105ea7a56cc61657f9822dd5baf39d8f1424929 Mon Sep 17 00:00:00 2001 From: cgfhtw Date: Thu, 23 Nov 2023 10:22:48 +0100 Subject: [PATCH] Interessenten anlegen (Debug Version) --- .../controllers/components/stv/Address.php | 47 ++ .../controllers/components/stv/Lists.php | 85 +++ .../controllers/components/stv/Student.php | 325 +++++++++-- .../components/stv/Studienplan.php | 41 ++ .../components/stv/Studiensemester.php | 15 +- public/js/components/Form/Validation.js | 25 +- .../js/components/Stv/Studentenverwaltung.js | 59 +- .../Studentenverwaltung/Details/Details.js | 39 +- .../Stv/Studentenverwaltung/List.js | 5 +- .../Stv/Studentenverwaltung/List/New.js | 516 ++++++++++++++---- .../Studentenverwaltung/Studiensemester.js | 21 +- public/js/directives/accessibility.js | 58 +- public/js/plugin/FhcAlert.js | 24 +- 13 files changed, 1016 insertions(+), 244 deletions(-) create mode 100644 application/controllers/components/stv/Address.php create mode 100644 application/controllers/components/stv/Lists.php create mode 100644 application/controllers/components/stv/Studienplan.php diff --git a/application/controllers/components/stv/Address.php b/application/controllers/components/stv/Address.php new file mode 100644 index 000000000..c0e34c0c3 --- /dev/null +++ b/application/controllers/components/stv/Address.php @@ -0,0 +1,47 @@ +load->model('codex/Nation_model', 'NationModel'); + + $this->NationModel->addOrder('kurztext'); + + $result = $this->NationModel->load(); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + $this->outputJson($result); + } + + public function getPlaces($plz) + { + $this->load->model('codex/Gemeinde_model', 'GemeindeModel'); + + $this->load->library('form_validation'); + + $this->form_validation->set_data(['address.plz' => $plz]); + + $this->form_validation->set_rules('address.plz', 'PLZ', 'numeric|less_than[10000]'); + + if ($this->form_validation->run() == false) { + $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST); + return $this->outputJsonError($this->form_validation->error_array()); + } + + $result = $this->GemeindeModel->getGemeindeByPlz($plz); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + $this->outputJson($result); + } +} diff --git a/application/controllers/components/stv/Lists.php b/application/controllers/components/stv/Lists.php new file mode 100644 index 000000000..959de7a12 --- /dev/null +++ b/application/controllers/components/stv/Lists.php @@ -0,0 +1,85 @@ +load->model('system/Sprache_model', 'SpracheModel'); + + $this->SpracheModel->addOrder('sprache'); + + $result = $this->SpracheModel->load(); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + $this->outputJson($result); + } + + public function getGeschlechter() + { + $this->load->model('person/Geschlecht_model', 'GeschlechtModel'); + + $this->GeschlechtModel->addOrder('sort'); + $this->GeschlechtModel->addOrder('geschlecht'); + + $this->GeschlechtModel->addSelect('*'); + $this->GeschlechtModel->addSelect("bezeichnung_mehrsprachig[(SELECT index FROM public.tbl_sprache WHERE sprache=" . $this->GeschlechtModel->escape(DEFAULT_LANGUAGE) . " LIMIT 1)] AS bezeichnung"); + + $result = $this->GeschlechtModel->load(); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + $this->outputJson($result); + } + + public function getAusbildungen() + { + $this->load->model('codex/Ausbildung_model', 'AusbildungModel'); + + $this->AusbildungModel->addOrder('ausbildungcode'); + + $result = $this->AusbildungModel->load(); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + $this->outputJson($result); + } + + public function getStgs() + { + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + + $this->StudiengangModel->addSelect('*'); + $this->StudiengangModel->addSelect('UPPER(typ || kurzbz) AS kuerzel'); + + $this->StudiengangModel->addOrder('typ'); + $this->StudiengangModel->addOrder('kurzbz'); + + $result = $this->StudiengangModel->loadWhere(['aktiv' => true]); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + $this->outputJson($result); + } + + public function getOrgforms() + { + $this->load->model('codex/Orgform_model', 'OrgformModel'); + + $this->OrgformModel->addOrder('bezeichnung'); + + $result = $this->OrgformModel->loadWhere(['rolle' => true]); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + $this->outputJson($result); + } +} diff --git a/application/controllers/components/stv/Student.php b/application/controllers/components/stv/Student.php index c59092c7f..4b1cbaf30 100644 --- a/application/controllers/components/stv/Student.php +++ b/application/controllers/components/stv/Student.php @@ -57,55 +57,6 @@ class Student extends FHC_Controller } } - public function getNations() - { - $this->load->model('codex/Nation_model', 'NationModel'); - - $this->NationModel->addOrder('kurztext'); - - $result = $this->NationModel->load(); - if (isError($result)) { - $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); - $this->outputJson(getError($result)); - } else { - $this->outputJson(getData($result) ?: []); - } - } - - public function getSprachen() - { - $this->load->model('system/Sprache_model', 'SpracheModel'); - - $this->SpracheModel->addOrder('sprache'); - - $result = $this->SpracheModel->load(); - if (isError($result)) { - $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); - $this->outputJson(getError($result)); - } else { - $this->outputJson(getData($result) ?: []); - } - } - - public function getGeschlechter() - { - $this->load->model('person/Geschlecht_model', 'GeschlechtModel'); - - $this->GeschlechtModel->addOrder('sort'); - $this->GeschlechtModel->addOrder('geschlecht'); - - $this->GeschlechtModel->addSelect('*'); - $this->GeschlechtModel->addSelect("bezeichnung_mehrsprachig[(SELECT index FROM public.tbl_sprache WHERE sprache=" . $this->GeschlechtModel->escape(DEFAULT_LANGUAGE) . " LIMIT 1)] AS bezeichnung"); - - $result = $this->GeschlechtModel->load(); - if (isError($result)) { - $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); - $this->outputJson($result); - } else { - $this->outputJsonSuccess(getData($result) ?: []); - } - } - public function save($prestudent_id) { $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell'); @@ -299,6 +250,282 @@ class Student extends FHC_Controller $this->outputJson($result); } + public function add() + { + $_POST = json_decode($this->input->raw_input_stream, true); + + if (!$this->input->post('person_id')) { + if (!isset($_POST['address']) || !is_array($_POST['address'])) + $_POST['address'] = []; + $_POST['address']['func'] = 1; + } + if ($this->input->post('incoming')) { + $_POST['ausbildungssemester'] = 0; + } + + $this->load->library('form_validation'); + + $this->form_validation->set_rules('nachname', 'Nachname', 'callback_requiredIfNotPersonId', [ + 'requiredIfNotPersonId' => $this->p->t('ui', 'error_required') + ]); + $this->form_validation->set_rules('geschlecht', 'Geschlecht', 'callback_requiredIfNotPersonId', [ + 'requiredIfNotPersonId' => $this->p->t('ui', 'error_required') + ]); + $this->form_validation->set_rules('gebdatum', 'Geburtsdatum', 'callback_isValidDate', [ + 'isValidDate' => $this->p->t('ui', 'error_invalid_date') + ]); + $this->form_validation->set_rules('address[func]', 'Address', 'required|integer|less_than[2]|greater_than[-2]'); + $this->form_validation->set_rules('address[plz]', 'PLZ', 'callback_requiredIfAddressFunc', [ + 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required') + ]); + $this->form_validation->set_rules('address[gemeinde]', 'Gemeinde', 'callback_requiredIfAddressFunc', [ + 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required') + ]); + $this->form_validation->set_rules('address[ort]', 'Ort', 'callback_requiredIfAddressFunc', [ + 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required') + ]); + $this->form_validation->set_rules('address[address]', 'Adresse', 'callback_requiredIfAddressFunc', [ + 'requiredIfAddressFunc' => $this->p->t('ui', 'error_required') + ]); + $this->form_validation->set_rules('email', 'E-Mail', 'valid_email'); + $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required'); + $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required'); + $this->form_validation->set_rules('ausbildungssemester', 'Ausbildungssemester', 'required|integer|less_than[9]|greater_than[-1]'); + // TODO(chris): validate studienplan with studiengang, semester and orgform? + // TODO(chris): validate person_id, studiengang_kz, studiensemester_kurzbz, orgform_kurzbz, nation, gemeinde, ort, geschlecht? + + if ($this->form_validation->run() == false) { + $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST); + return $this->outputJsonError($this->form_validation->error_array()); + } + + // TODO(chris): This should be in a library + $this->load->model('crm/Prestudent_model', 'PrestudentModel'); + $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + + $this->db->trans_start(); + + $result = $this->addInteressent(); + + $this->db->trans_complete(); + + if ($this->db->trans_status() === FALSE) { + return $this->outputJsonSuccess(true); // TODO(chris): DEBUG! REMOVE! + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + + $this->outputJson($result); + } + + protected function addInteressent() + { + // Person anlegen wenn nötig + $person_id = $this->input->post('person_id'); + if (!$person_id) { + $this->load->model('person/Person_model', 'PersonModel'); + + $data = [ + 'nachname' => $this->input->post('nachname'), + 'insertamum' => date('c'), + 'insertvon' => getAuthUID(), + 'zugangscode' => uniqid(), + 'aktiv' => true + ]; + if ($this->input->post('anrede')) + $data['anrede'] = $this->input->post('anrede'); + if ($this->input->post('titelpre')) + $data['titelpre'] = $this->input->post('titelpre'); + if ($this->input->post('titelpost')) + $data['titelpost'] = $this->input->post('titelpost'); + if ($this->input->post('vorname')) + $data['vorname'] = $this->input->post('vorname'); + if ($this->input->post('vornamen')) + $data['vornamen'] = $this->input->post('vornamen'); + if ($this->input->post('wahlname')) + $data['wahlname'] = $this->input->post('wahlname'); + if ($this->input->post('geschlecht')) + $data['geschlecht'] = $this->input->post('geschlecht'); + if ($this->input->post('gebdatum')) + $data['gebdatum'] = (new DateTime($this->input->post('datum_obj')))->format('Y-m-d'); + if ($this->input->post('geburtsnation')) + $data['geburtsnation'] = $this->input->post('geburtsnation'); + if ($this->input->post('staatsbuergerschaft')) + $data['staatsbuergerschaft'] = $this->input->post('staatsbuergerschaft'); + + $result = $this->PersonModel->insert($data); + if (isError($result)) + return $result; + $person_id = getData($result); + } + + // Addresse anlegen + $anlegen = $this->input->post('address[func]'); + if ($anlegen) { + $this->load->model('person/Adresse_model', 'AdresseModel'); + + $data = [ + 'nation' => $this->input->post('address[nation]'), + 'strasse' => $this->input->post('address[address]'), + 'plz' => $this->input->post('address[plz]'), + 'ort' => $this->input->post('address[ort]'), + 'gemeinde' => $this->input->post('address[gemeinde]'), + 'typ' => 'h', + 'zustelladresse' => true, + ]; + if ($anlegen < 0) { // Überschreiben + $this->AdresseModel->addOrder('zustelladresse', 'DESC'); + $this->AdresseModel->addOrder('sort'); + $result = $this->AdresseModel->loadWhere([ + 'person_id' => $person_id + ]); + if (isError($result)) + return $result; + if (hasData($result)) { + $address = current(getData($result)); + + $data['updateamum'] = date('c'); + $data['updatevon'] = getAuthUID(); + + $result = $this->AdresseModel->update($address->adresse_id, $data); + if (isError($result)) + return $result; + } else { + //Wenn keine Adrese vorhanden ist dann eine neue Anlegen + $anlegen = 1; + $data['heimatadresse'] = true; + } + } + if ($anlegen > 0) { + $data['person_id'] = $person_id; + $data['insertamum'] = date('c'); + $data['insertvon'] = getAuthUID(); + if (!isset($data['heimatadresse'])) + $data['heimatadresse'] = !$this->input->post('person_id'); + + $result = $this->AdresseModel->insert($data); + if (isError($result)) + return $result; + } + } + + // Kontaktdaten + $kontaktdaten = []; + foreach (['email', 'telefon', 'mobil'] as $k) { + $v = $this->input->post($k); + if ($v) + $kontaktdaten[$k] = $v; + } + if (count($kontaktdaten)) { + $this->load->model('person/Kontakt_model', 'KontaktModel'); + + foreach ($kontaktdaten as $typ => $kontakt) { + $data = [ + 'person_id' => $person_id, + 'kontakttyp' => $typ, + 'kontakt' => $kontakt, + 'zustellung' => true, + 'insertamum' => date('c'), + 'insertvon' => getAuthUID() + ]; + $result = $this->KontaktModel->insert($data); + if (isError($result)) + return $result; + } + } + + // Prestudent anlegen + $data = [ + 'aufmerksamdurch_kurzbz' => 'k.A.', + 'person_id' => $person_id, + 'studiengang_kz' => $this->input->post('studiengang_kz'), + 'ausbildungcode' => $this->input->post('letzteausbildung'), + 'anmerkung' => $this->input->post('anmerkungen'), + 'reihungstestangetreten' => false, + 'bismelden' => true + ]; + $ausbildungsart = $this->input->post('ausbildungsart'); + if ($ausbildungsart) + $data['anmerkung'] .= ' Ausbildungsart:' . $ausbildungsart; + // Incomings und ausserordentliche sind bei Meldung nicht förderrelevant + $incoming = $this->input->post('incoming'); + if ($incoming || substr($data['studiengang_kz'], 0, 1) == '9') + $data['foerderrelevant'] = false; + // Wenn die Person schon im System erfasst ist, dann die ZGV des Datensatzes uebernehmen + $this->PrestudentModel->addOrder('zgvmas_code'); + $this->PrestudentModel->addOrder('zgv_code', 'DESC'); + $this->PrestudentModel->addLimit(1); + $result = $this->PrestudentModel->loadWhere([ + 'person_id' => $person_id + ]); + if (isError($result)) + return $result; + if (hasData($result)) { + $prestudent = current(getData($result)); + if ($prestudent->zgv_code) { + $data['zgv_code'] = $prestudent->zgv_code; + $data['zgvort'] = $prestudent->zgvort; + $data['zgvdatum'] = $prestudent->zgvdatum; + + $data['zgvmas_code'] = $prestudent->zgvmas_code; + $data['zgvmaort'] = $prestudent->zgvmaort; + $data['zgvmadatum'] = $prestudent->zgvmadatum; + } + } + // Prestudent speichern + $result = $this->PrestudentModel->insert($data); + if (isError($result)) + return $result; + $prestudent_id = getData($result); + + // Prestudent Rolle Anlegen + $data = [ + 'prestudent_id' => $prestudent_id, + 'status_kurzbz' => $incoming ? 'Incoming' : 'Interessent', + 'studiensemester_kurzbz' => $this->input->post('studiensemester_kurzbz'), + 'ausbildungssemester' => $this->input->post('ausbildungssemester') ?: 0, + 'orgform_kurzbz' => $this->input->post('orgform_kurzbz') ?: null, + 'studienplan_id' => $this->input->post('studienplan_id') ?: null, + 'datum' => date('Y-m-d'), + 'insertamum' => date('c'), + 'insertvon' => getAuthUID() + ]; + $result = $this->PrestudentstatusModel->insert($data); + if (isError($result)) + return $result; + + if ($incoming) { + // TODO(chris): IMPLEMENT! + //Matrikelnummer und UID generieren + //Benutzerdatensatz anlegen + //Studentendatensatz anlegen + //StudentLehrverband anlegen + } + + // TODO(chris): DEBUG + $result = $this->PrestudentModel->loadWhere([ + 'pestudent_id' => 1 + ]); + if (isError($result)) { + return $result; + } + + return success(true); + } + + public function requiredIfNotPersonId($value) + { + if (isset($_POST['person_id'])) + return true; + return !!$value; + } + + public function requiredIfAddressFunc($value) + { + if (!$_POST['address']['func']) + return true; + return !!$value; + } + public function isValidDate($date) { try { diff --git a/application/controllers/components/stv/Studienplan.php b/application/controllers/components/stv/Studienplan.php new file mode 100644 index 000000000..2e7c2f425 --- /dev/null +++ b/application/controllers/components/stv/Studienplan.php @@ -0,0 +1,41 @@ +load->model('organisation/Studienplan_model', 'StudienplanModel'); + + $_POST = json_decode($this->input->raw_input_stream, true); + + $this->load->library('form_validation'); + + $this->form_validation->set_rules('studiengang_kz', 'StudiengangKz', 'required|numeric'); + $this->form_validation->set_rules('studiensemester_kurzbz', 'StudiensemesterKurbz', 'required'); + $this->form_validation->set_rules('ausbildungssemester', 'Ausbildungssemester', 'numeric'); + + if ($this->form_validation->run() == false) { + $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST); + return $this->outputJsonError($this->form_validation->error_array()); + } + + $studiengang_kz = $this->input->post('studiengang_kz'); + $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz'); + $ausbildungssemester = $this->input->post('ausbildungssemester') ?: null; + $orgform_kurzbz = $this->input->post('orgform_kurzbz') ?: null; + + $result = $this->StudienplanModel->getStudienplaeneBySemester($studiengang_kz, $studiensemester_kurzbz, $ausbildungssemester, $orgform_kurzbz); + if (isError($result)) { + $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); + } + $this->outputJson($result); + } +} diff --git a/application/controllers/components/stv/Studiensemester.php b/application/controllers/components/stv/Studiensemester.php index 88c95cd71..09bbf8886 100644 --- a/application/controllers/components/stv/Studiensemester.php +++ b/application/controllers/components/stv/Studiensemester.php @@ -20,13 +20,8 @@ class Studiensemester extends FHC_Controller if (isError($result)) { $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); - $this->outputJson(getError($result)); - } elseif (!hasData($result)) { - $this->output->set_status_header(REST_Controller::HTTP_NOT_FOUND); - $this->outputJson('NOT FOUND'); - } else { - $this->outputJson(getData($result)); } + $this->outputJson($result); } public function now() @@ -43,9 +38,9 @@ class Studiensemester extends FHC_Controller if (count($result) != 1) { $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); - $this->outputJson(count($result) ? 'Mehrere Studiensemester aktiv' : 'Kein Studiensemester aktiv'); + $this->outputJsonError(count($result) ? 'Mehrere Studiensemester aktiv' : 'Kein Studiensemester aktiv'); } else { - $this->outputJson(current($result)->studiensemester_kurzbz); + $this->outputJsonSuccess(current($result)->studiensemester_kurzbz); } } @@ -60,7 +55,7 @@ class Studiensemester extends FHC_Controller if ($this->form_validation->run() == false) { $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST); - return $this->outputJson($this->form_validation->error_array()); + return $this->outputJsonError($this->form_validation->error_array()); } $stdsem = $this->input->post('studiensemester'); @@ -71,7 +66,7 @@ class Studiensemester extends FHC_Controller if (isError($result)) { $this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR); - return $this->outputJson(getError($result)); + return $this->outputJson($result); } $this->outputJsonSuccess(true); diff --git a/public/js/components/Form/Validation.js b/public/js/components/Form/Validation.js index 78408e8e8..3b4e69112 100644 --- a/public/js/components/Form/Validation.js +++ b/public/js/components/Form/Validation.js @@ -42,13 +42,16 @@ export default { const res = this.$slots.default(); const orig = res.shift(); + let options = { 'data-fhc-form-validate': this.name, onFhcFormReset: this.reset, onFhcFormValidate: this.setValid, onFhcFormInvalidate: this.setInvalid, + onInput: this.reset, class: { - 'form-control': true, + 'form-control': orig.type !== 'select' && orig.props.type !== 'checkbox' && orig.props.type !== 'radio' && !(orig.props?.class || '').split(' ').includes('form-control'), + 'form-select': orig.type === 'select' && !(orig.props?.class || '').split(' ').includes('form-select'), 'is-valid': this.isValid, 'is-invalid': this.isInvalid } @@ -59,11 +62,23 @@ export default { } res.unshift(Vue.cloneVNode(orig, options)); - if (this.isInvalid && this.invalidFeedback && this.$slots.default) - res.push(Vue.h('div', { + if (this.isInvalid && this.invalidFeedback && this.$slots.default) { + /* NOTE(chris): use bootstraps 'feedback' */ + /*res.push(Vue.h('div', { class: 'invalid-feedback' - }, this.invalidFeedback)); + }, this.invalidFeedback));*/ - return res; + /* NOTE(chris): use bootstraps 'tooltip' */ + res.push(Vue.h('div', { + class: 'invalid-tooltip' + }, this.invalidFeedback)); + } + /* NOTE(chris): use bootstraps 'feedback' */ + /*return res;*/ + + /* NOTE(chris): use bootstraps 'tooltip' */ + return Vue.h('div', { + class: 'position-relative' + }, res); }, }; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung.js b/public/js/components/Stv/Studentenverwaltung.js index f2fd2ac36..9cd3f0b57 100644 --- a/public/js/components/Stv/Studentenverwaltung.js +++ b/public/js/components/Stv/Studentenverwaltung.js @@ -21,6 +21,7 @@ import StvVerband from "./Studentenverwaltung/Verband.js"; import StvList from "./Studentenverwaltung/List.js"; import StvDetails from "./Studentenverwaltung/Details.js"; import StvStudiensemester from "./Studentenverwaltung/Studiensemester.js"; +import {CoreRESTClient} from '../../RESTClient.js'; export default { @@ -46,7 +47,8 @@ export default { activeAddonBewerbung: this.activeAddons.split(';').includes('bewerbung'), configGenerateAlias: this.config.generateAlias, hasBpkPermission: this.permissions['student/bpk'], - hasAliasPermission: this.permissions['student/alias'] + hasAliasPermission: this.permissions['student/alias'], + lists: this.lists } }, data() { @@ -81,6 +83,12 @@ export default { } }, studiengangKz: undefined, + studiensemesterKurzbz: this.defaultSemester, + lists: { + nations: [], + sprachen: [], + geschlechter: [] + } } }, computed: { @@ -96,10 +104,55 @@ export default { searchfunction(searchsettings) { return Vue.$fhcapi.Search.search(searchsettings); }, - studiensemesterChanged() { + studiensemesterChanged(v) { + this.studiensemesterKurzbz = v; this.$refs.stvList.updateUrl(); } }, + created() { + CoreRESTClient + .get('components/stv/Address/getNations') + .then(result => CoreRESTClient.getData(result.data) || []) + .then(result => { + this.lists.nations = result; + }) + .catch(this.$fhcAlert.handleSystemError); + CoreRESTClient + .get('components/stv/Lists/getSprachen') + .then(result => CoreRESTClient.getData(result.data) || []) + .then(result => { + this.lists.sprachen = result; + }) + .catch(this.$fhcAlert.handleSystemError); + CoreRESTClient + .get('components/stv/Lists/getGeschlechter') + .then(result => CoreRESTClient.getData(result.data) || []) + .then(result => { + this.lists.geschlechter = result; + }) + .catch(this.$fhcAlert.handleSystemError); + CoreRESTClient + .get('components/stv/Lists/getAusbildungen') + .then(result => CoreRESTClient.getData(result.data) || []) + .then(result => { + this.lists.ausbildungen = result; + }) + .catch(this.$fhcAlert.handleSystemError); + CoreRESTClient + .get('components/stv/Lists/getStgs') + .then(result => CoreRESTClient.getData(result.data) || []) + .then(result => { + this.lists.stgs = result; + }) + .catch(this.$fhcAlert.handleSystemError); + CoreRESTClient + .get('components/stv/Lists/getOrgforms') + .then(result => CoreRESTClient.getData(result.data) || []) + .then(result => { + this.lists.orgforms = result; + }) + .catch(this.$fhcAlert.handleSystemError); + }, mounted() { if (this.$route.params.id) { this.$refs.stvList.updateUrl('components/stv/students/uid/' + this.$route.params.id, true); @@ -126,7 +179,7 @@ export default {
` diff --git a/public/js/components/Stv/Studentenverwaltung/Studiensemester.js b/public/js/components/Stv/Studentenverwaltung/Studiensemester.js index 24a9e7206..c52d584fd 100644 --- a/public/js/components/Stv/Studentenverwaltung/Studiensemester.js +++ b/public/js/components/Stv/Studentenverwaltung/Studiensemester.js @@ -49,20 +49,17 @@ export default { this.loading = true; CoreRESTClient .get('components/stv/studiensemester/now') - .then(result => result.data) + .then(result => CoreRESTClient.getData(result.data)) .then(result => { this.today = this.list.indexOf(result); - if (this.today > 0) { + if (this.today >= 0) { if (this.today != this.current) this.set(this.today); } else { // TODO(chris): handle error (list might not be loaded yet) } }) - .catch(error => { - // TODO(chris): emit error - console.error(error); - }); + .catch(this.$fhcAlert.handleSystemError); }, save(fallback) { CoreRESTClient @@ -71,27 +68,25 @@ export default { }) .then(() => { this.loading = false; - this.$emit('changed'); + this.$emit('changed', this.list[this.current]); }) .catch(error => { this.current = fallback; - // TODO(chris): emit error - console.error(error); + this.loading = false; + this.$fhcAlert.handleFormValidation(error); }); } }, created() { CoreRESTClient .get('components/stv/studiensemester') - .then(result => result.data) + .then(result => CoreRESTClient.getData(result.data) || []) .then(result => { this.list = result.map(el => el.studiensemester_kurzbz); this.loading = false; this.current = this.list.indexOf(this.default); }) - .catch(error => { - console.error(error); - }); + .catch(this.$fhcAlert.handleSystemError); }, template: `
diff --git a/public/js/directives/accessibility.js b/public/js/directives/accessibility.js index e8b11b61d..77ca8f428 100644 --- a/public/js/directives/accessibility.js +++ b/public/js/directives/accessibility.js @@ -2,32 +2,33 @@ export default { created(el, binding) { switch (binding.arg) { case 'tab': + el.style.cursor = 'pointer'; const [prev, next] = binding.modifiers.vertical ? ['ArrowUp', 'ArrowDown'] : ['ArrowLeft', 'ArrowRight']; el.addEventListener('click', () => { let act = el.parentNode.querySelector('[tabindex="0"]'); if (act) - act.setAttribute('tabindex', -1); - el.setAttribute('tabindex', 0); + act.tabIndex = -1; + el.tabIndex = 0; }); el.addEventListener('focus', () => { - el.setAttribute('aria-selected', true); + el.ariaSelected = "true"; }); el.addEventListener('blur', () => { - el.setAttribute('aria-selected', false); + el.ariaSelected = "false"; }); el.addEventListener('keydown', e => { switch (e.code) { case prev: - if (el.previousSibling?.setAttribute) { - el.previousSibling.setAttribute('tabindex', 0); - el.setAttribute('tabindex', -1); + if (el.previousSibling?.tabIndex !== undefined) { + el.previousSibling.tabIndex = 0; + el.tabIndex = -1; el.previousSibling.focus(); } break; case next: - if (el.nextSibling?.setAttribute) { - el.nextSibling.setAttribute('tabindex', 0); - el.setAttribute('tabindex', -1); + if (el.nextSibling?.tabIndex !== undefined) { + el.nextSibling.tabIndex = 0; + el.tabIndex = -1; el.nextSibling.focus(); } break; @@ -44,18 +45,18 @@ export default { case 'tab': let activetab = -1; Array.from(el.parentNode.children).forEach((node, index) => { - node.setAttribute('aria-setsize', el.parentNode.children.length); - node.setAttribute('aria-posinset', index); - if (node.getAttribute('tabindex') == '0') + node.ariaSetSize = el.parentNode.children.length; + node.ariaPosInSet = index; + if (node.tabIndex === 0) activetab = index; }); if (activetab == -1) { - el.setAttribute('tabindex', 0); + el.tabIndex = 0; } else if (el.classList.contains('active')) { - el.parentNode.children[activetab].setAttribute('tabindex', -1); - el.setAttribute('tabindex', 0); + el.parentNode.children[activetab].tabIndex = -1; + el.tabIndex = 0; } else { - el.setAttribute('tabindex', -1); + el.tabIndex = -1; } break; } @@ -63,26 +64,19 @@ export default { beforeUnmount(el, binding) { switch (binding.arg) { case 'tab': - if (el.getAttribute('tabindex') == '0') { - if (el.previousSibling?.setAttribute) - el.previousSibling.setAttribute('tabindex', 0); - else if (el.nextSibling?.setAttribute) - el.nextSibling.setAttribute('tabindex', 0); + if (el.tabIndex === 0) { + if (el.previousSibling?.tabIndex !== undefined) + el.previousSibling.tabIndex = 0; + else if (el.nextSibling?.tabIndex !== undefined) + el.nextSibling.tabIndex = 0; } - const pos = parseInt(el.getAttribute('aria-posinset')); + const pos = parseInt(el.ariaPosInSet); Array.from(el.parentNode.children).forEach((node, index) => { - node.setAttribute('aria-setsize', el.parentNode.children.length-1); + node.ariaSetSize = el.parentNode.children.length; if (index > pos) - node.setAttribute('aria-posinset', index-1); + node.ariaPosInSet = index-1; }); break; } - }, - unmounted(el, binding) { - switch (binding.arg) { - case 'tab': - console.log(el.parentNode); - break; - } } } \ No newline at end of file diff --git a/public/js/plugin/FhcAlert.js b/public/js/plugin/FhcAlert.js index b232c813a..079039aed 100644 --- a/public/js/plugin/FhcAlert.js +++ b/public/js/plugin/FhcAlert.js @@ -97,6 +97,8 @@ import PvToast from "../../../index.ci.php/public/js/components/primevue/toast/t import PvConfirm from "../../../index.ci.php/public/js/components/primevue/confirmdialog/confirmdialog.esm.min.js"; import PvConfirmationService from "../../../index.ci.php/public/js/components/primevue/confirmationservice/confirmationservice.esm.min.js"; +import {CoreRESTClient} from '../RESTClient.js'; + const helperAppContainer = document.createElement('div'); const helperApp = Vue.createApp({ @@ -181,18 +183,28 @@ export default { install: (app, options) => { const $fhcAlert = { alertSuccess(message) { + if (Array.isArray(message)) + return message.forEach(this.alertSuccess); helperAppInstance.$refs.toast.add({ severity: 'success', summary: 'Info', detail: message, life: 1000}); }, alertInfo(message) { + if (Array.isArray(message)) + return message.forEach(this.alertInfo); helperAppInstance.$refs.toast.add({ severity: 'info', summary: 'Info', detail: message, life: 3000 }); }, alertWarning(message) { + if (Array.isArray(message)) + return message.forEach(this.alertWarning); helperAppInstance.$refs.toast.add({ severity: 'warn', summary: 'Achtung', detail: message}); }, alertError(message) { + if (Array.isArray(message)) + return message.forEach(this.alertError); helperAppInstance.$refs.toast.add({ severity: 'error', summary: 'Achtung', detail: message }); }, alertSystemError(message) { + if (Array.isArray(message)) + return message.forEach(this.alertSystemError); helperAppInstance.$refs.alert.add({ severity: 'error', summary: 'Systemfehler', detail: message}); }, confirmDelete() { @@ -243,7 +255,9 @@ export default { if (typeof error === 'object' && error !== null) { let errMsg = ''; - if (error.hasOwnProperty('message')) + if (error.hasOwnProperty('response') && error.response?.data?.retval) + errMsg += 'Error Message: ' + (error.response.data.retval.message || error.response.data.retval) + '\r\n'; + else if (error.hasOwnProperty('message')) errMsg += 'Error Message: ' + error.message.toUpperCase() + '\r\n'; if (error.hasOwnProperty('config') && error.config.hasOwnProperty('url')) @@ -366,7 +380,13 @@ export default { return; } } - $fhcAlert.handleSystemError(error); + + if (error?.response?.status == 400) { + let errors = CoreRESTClient.getError(error.response.data); + $fhcAlert.alertError((typeof errors === 'object') ? Object.values(errors) : errors); + } else { + $fhcAlert.handleSystemError(error); + } } }; app.config.globalProperties.$fhcAlert = $fhcAlert;