Interessenten anlegen (Debug Version)

This commit is contained in:
cgfhtw
2023-11-23 10:22:48 +01:00
parent 3674315305
commit d105ea7a56
13 changed files with 1016 additions and 244 deletions
@@ -0,0 +1,47 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Address extends FHC_Controller
{
public function __construct()
{
// TODO(chris): access!
parent::__construct();
}
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($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);
}
}
@@ -0,0 +1,85 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Lists extends FHC_Controller
{
public function __construct()
{
// TODO(chris): access!
parent::__construct();
}
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($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);
}
}
@@ -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 {
@@ -0,0 +1,41 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Studienplan extends FHC_Controller
{
public function __construct()
{
// TODO(chris): access!
parent::__construct();
}
public function get()
{
$this->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);
}
}
@@ -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);
+20 -5
View File
@@ -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);
},
};
@@ -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 {
<main class="col-md-8 ms-sm-auto col-lg-9 col-xl-10">
<vertical-split>
<template #top>
<stv-list ref="stvList" v-model:selected="selected" :studiengang-kz="studiengangKz"></stv-list>
<stv-list ref="stvList" v-model:selected="selected" :studiengang-kz="studiengangKz" :studiensemester-kurzbz="studiensemesterKurzbz"></stv-list>
</template>
<template #bottom>
<stv-details :student="lastSelected"></stv-details>
@@ -31,6 +31,9 @@ export default {
hasAliasPermission: {
from: 'hasAliasPermission',
default: false
},
lists: {
from: 'lists'
}
},
props: {
@@ -38,9 +41,6 @@ export default {
},
data() {
return {
nations: [],
sprachen: [],
geschlechter: [],
familienstaende: {
"": "--keine Auswahl--",
"g": "geschieden",
@@ -169,31 +169,6 @@ export default {
}
},
created() {
CoreRESTClient
.get('components/stv/Student/getNations')
.then(result => {
this.nations = result.data;
})
.catch(err => {
console.error(err.response.data || err.message);
});
CoreRESTClient
.get('components/stv/Student/getSprachen')
.then(result => {
this.sprachen = result.data;
})
.catch(err => {
console.error(err.response.data || err.message);
});
CoreRESTClient
.get('components/stv/Student/getGeschlechter')
.then(result => CoreRESTClient.getData(result.data))
.then(result => {
this.geschlechter = result.data;
})
.catch(err => {
console.error(CoreRestClient.getError(err.response.data) || err.message);
});
this.updateStudent(this.student);
},
//TODO(chris): Geburtszeit? Anzahl der Kinder?
@@ -269,7 +244,7 @@ export default {
<select id="stv-details-geburtsnation" class="form-control" v-model="data.geburtsnation">
<option value="">-- keine Auswahl --</option>
<!-- TODO(chris): gesperrte nationen können nicht ausgewählt werden! Um das zu realisieren müsste man ein pseudo select machen -->
<option v-for="nation in nations" :key="nation.nation_code" :value="nation.nation_code" :disabled="nation.sperre">{{nation.kurztext}}</option>
<option v-for="nation in lists.nations" :key="nation.nation_code" :value="nation.nation_code" :disabled="nation.sperre">{{nation.kurztext}}</option>
</select>
</div>
</div>
@@ -289,7 +264,7 @@ export default {
<select id="stv-details-staatsbuergerschaft" class="form-control" v-model="data.staatsbuergerschaft">
<option value="">-- keine Auswahl --</option>
<!-- TODO(chris): gesperrte nationen können nicht ausgewählt werden! Um das zu realisieren müsste man ein pseudo select machen -->
<option v-for="nation in nations" :key="nation.nation_code" :value="nation.nation_code" :disabled="nation.sperre">{{nation.kurztext}}</option>
<option v-for="nation in lists.nations" :key="nation.nation_code" :value="nation.nation_code" :disabled="nation.sperre">{{nation.kurztext}}</option>
</select>
</div>
<label for="stv-details-matr_nr" class="col-sm-1 col-form-label">Matrikelnummer</label>
@@ -299,7 +274,7 @@ export default {
<label for="stv-details-sprache" class="col-sm-1 col-form-label">Sprache</label>
<div class="col-sm-3">
<select id="stv-details-sprache" class="form-control" v-model="data.sprache">
<option v-for="sprache in sprachen" :key="sprache.sprache" :value="sprache.sprache">{{sprache.sprache}}</option>
<option v-for="sprache in lists.sprachen" :key="sprache.sprache" :value="sprache.sprache">{{sprache.sprache}}</option>
</select>
</div>
</div>
@@ -307,7 +282,7 @@ export default {
<label for="stv-details-geschlecht" class="col-sm-1 col-form-label">Geschlecht</label>
<div class="col-sm-3">
<select id="stv-details-geschlecht" class="form-control" v-model="data.geschlecht">
<option v-for="geschlecht in geschlechter" :key="geschlecht.geschlecht" :value="geschlecht.geschlecht">{{geschlecht.bezeichnung}}</option>
<option v-for="geschlecht in lists.geschlechter" :key="geschlecht.geschlecht" :value="geschlecht.geschlecht">{{geschlecht.bezeichnung}}</option>
</select>
</div>
<label for="stv-details-familienstand" class="col-sm-1 col-form-label">Familienstand</label>
@@ -9,7 +9,8 @@ export default {
},
props: {
selected: Array,
studiengangKz: Number
studiengangKz: Number,
studiensemesterKurzbz: String
},
emits: [
'update:selected'
@@ -180,6 +181,6 @@ export default {
tabindex="0"
>
</core-filter-cmpt>
<list-new ref="new" studiengang-kz="studiengangKz"></list-new>
<list-new ref="new" :studiengang-kz="studiengangKz" :studiensemester-kurzbz="studiensemesterKurzbz"></list-new>
</div>`
};
@@ -5,6 +5,17 @@ import VueDatePicker from '../../../vueDatepicker.js.php';
import accessibility from '../../../../directives/accessibility.js';
var _uuid = 0;
const FORMDATA_DEFAULT = {
address: {
func: 0,
nation: 'A'
},
geburtsnation: 'A',
staatsbuergerschaft: 'A',
ausbildungssemester: 1,
orgform_kurzbz: '',
studienplan_id: ''
};
export default {
components: {
@@ -15,29 +26,65 @@ export default {
directives: {
accessibility
},
inject: [
'lists'
],
props: {
studiengangKz: Number
studiengangKz: Number,
studiensemesterKurzbz: String
},
data() {
return {
geschlechter: [],
formData: {},
places: [],
formData: FORMDATA_DEFAULT,
suggestions: {},
person: null
person: null,
semester: [],
studienplaene: [],
abortController: {
suggestions: null,
places: null
}
}
},
computed: {
saveTitle() {
if (this.person === null)
return 'Bitte auswählen';
if (this.person === 0)
return 'Neue Person anlegen';
return 'zu ' + (this.person.vorname + ' ' + this.person.nachname).trim() + ' hinzufügen';
},
formDataPerson() {
if (this.person)
return this.person;
return this.formData;
},
orte() {
return this.places.filter(ort => ort.name == this.formData.address.gemeinde);
},
gemeinden() {
return Object.values(this.places.reduce((res,place) => {
res[place.name] = place;
return res;
}, {}));
},
formDataStg: {
get() {
return this.formData.studiengang_kz !== undefined ? this.formData.studiengang_kz : this.studiengangKz;
},
set(v) {
this.formData.studiengang_kz = v;
}
},
formDataSem: {
get() {
return this.formData.studiensemester_kurzbz !== undefined ? this.formData.studiensemester_kurzbz : this.studiensemesterKurzbz;
},
set(v) {
this.formData.studiensemester_kurzbz = v;
}
}
},
watch: {
formDataStg() {
this.loadStudienplaene();
},
formDataSem() {
this.loadStudienplaene();
}
},
methods: {
@@ -45,38 +92,103 @@ export default {
this.$refs.modal.show();
},
reset() {
this.formData = {};
this.formData = FORMDATA_DEFAULT;
this.person = null;
this.suggestions = [];
this.$fhcAlert.resetFormValidation(this.$refs.form)
},
loadSuggestions() {
if (this.person)
if (this.abortController.suggestions)
this.abortController.suggestions.abort();
if (this.person !== null)
return;
// TODO(chris): load serialized
this.abortController.suggestions = new AbortController();
CoreRESTClient
.post('components/stv/student/check', {
vorname: this.formData.vorname,
nachname: this.formData.nachname,
gebdatum: this.formData.gebdatum
}, {
signal: this.abortController.suggestions.signal
})
.then(result => CoreRESTClient.getData(result.data) || [])
.then(result => {
this.suggestions = result;
})
.catch(() => {
.catch(error => {
// NOTE(chris): repeat request
window.setTimeout(this.loadSuggestions, 100);
if (error.code != "ERR_CANCELED")
window.setTimeout(this.loadSuggestions, 100);
});
},
send(e) {
if (e.person === null)
this.$fhcAlert.alertError('Select a person first'); // TODO(chris): better error handling!
loadPlaces() {
if (this.abortController.places)
this.abortController.places.abort();
if (this.formData.address.nation != 'A' || !this.formData.address.plz)
return;
this.$fhcAlert.resetFormValidation(form);
const data = {...this.formData, ...(this.person || {})};
this.abortController.places = new AbortController();
CoreRESTClient
.post('components/stv/student/add')
.get('components/stv/address/getPlaces/' + this.formData.address.plz, undefined, {
signal: this.abortController.places.signal
})
.then(result => CoreRESTClient.getData(result.data) || [])
.then(result => {
this.places = result;
})
.catch(error => {
if (error.code == 'ERR_BAD_REQUEST') {
return this.$fhcAlert.handleFormValidation(error, this.$refs.form);
}
// NOTE(chris): repeat request
if (error.code != "ERR_CANCELED")
window.setTimeout(this.loadPlaces, 100);
});
},
loadStudienplaene() {
CoreRESTClient
.post('components/stv/studienplan/get', {
studiengang_kz: this.formDataStg,
studiensemester_kurzbz: this.formDataSem,
ausbildungssemester: this.formData.ausbildungssemester,
orgform_kurzbz: this.formData.orgform_kurzbz
})
.then(result => CoreRESTClient.getData(result.data) || [])
.then(result => {
this.studienplaene = result;
if (this.formData.studienplan_id !== '' && !this.studienplaene.filter(plan => plan.studienplan_id == this.formData.studienplan_id).length)
this.formData.studienplan_id = '';
})
.catch(error => {
if (error.code == 'ERR_BAD_REQUEST') {
return this.studienplaene = [];
}
// NOTE(chris): repeat request
if (error.code != "ERR_CANCELED")
window.setTimeout(this.loadStudienplaene, 100);
})
},
changeAddressNation(e) {
if (this.formData['geburtsnation'] == this.formData['address']['nation'])
this.formData['geburtsnation'] = e.target.value;
if (this.formData['staatsbuergerschaft'] == this.formData['address']['nation'])
this.formData['staatsbuergerschaft'] = e.target.value;
this.loadPlaces();
},
send(e) {
if (this.person === null)
return this.person = 0;
this.$fhcAlert.resetFormValidation(this.$refs.form);
const data = {...this.formData, ...(this.person || {})};
if (data.studiengang_kz === undefined)
data.studiengang_kz = this.studiengangKz;
if (data.studiensemester_kurzbz === undefined)
data.studiensemester_kurzbz = this.studiensemesterKurzbz;
CoreRESTClient
.post('components/stv/student/add', data)
.then(result => result.data)
.then(result => {
if (CoreRESTClient.isError(result))
@@ -85,108 +197,320 @@ export default {
})
.then(result => {
this.$fhcAlert.alertSuccess('Gespeichert');
console.log('saved');
// TODO(chris): close
this.$refs.modal.hide();
})
.catch(this.$fhcAlert.handleFormValidation);
.catch(this.$fhcAlert.handleFormValidation(this.$refs.form));
}
},
created() {
this.uuid = _uuid++;
// TODO(chris): geschlechter in parent?
CoreRESTClient
.get('components/stv/Student/getGeschlechter')
.then(result => CoreRESTClient.getData(result.data))
.get('components/stv/Studiensemester')
.then(result => CoreRESTClient.getData(result.data) || [])
.then(result => {
this.geschlechter = result;
this.semester = result;
})
.catch(this.$fhcAlert.handleSystemError);
},
template: `
<form ref="form" class="stv-list-new" @submit.prevent="send">
<bs-modal ref="modal" dialog-class="modal-fullscreen" @hidden-bs-modal="reset">
<bs-modal ref="modal" dialog-class="modal-lg modal-scrollable" @hidden-bs-modal="reset">
<template #title>
InteressentIn anlegen
</template>
<template #default>
<fhc-form-validation></fhc-form-validation>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-anrede-' + uuid">Anrede</label>
<fhc-form-validation name="anrede">
<input :id="'stv-list-new-anrede-' + uuid" type="text" name="anrede" v-model="formDataPerson['anrede']" class="form-control" :disabled="person">
</fhc-form-validation>
<template v-if="person === null">
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-nachname-' + uuid">Nachname*</label>
<fhc-form-validation name="nachname">
<input :id="'stv-list-new-nachname-' + uuid" type="text" name="nachname" v-model="formDataPerson['nachname']" class="form-control" :disabled="person" @input="loadSuggestions">
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-vorname-' + uuid">Vorname</label>
<fhc-form-validation name="vorname">
<input :id="'stv-list-new-vorname-' + uuid" type="text" name="vorname" v-model="formDataPerson['vorname']" class="form-control" :disabled="person" @input="loadSuggestions">
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'dp-input-stv-list-new-gebdatum-' + uuid">Geburtsdatum</label>
<fhc-form-validation name="gebdatum">
<vue-date-picker :uid="'stv-list-new-gebdatum-' + uuid" name="gebdatum" text-input auto-apply no-today v-model="formDataPerson['gebdatum']" :enable-time-picker="false" format="dd.MM.yyyy" @update:model-value="loadSuggestions" :disabled="person"></vue-date-picker>
</fhc-form-validation>
</div>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-titelpre-' + uuid">Titel (Pre)</label>
<fhc-form-validation name="titelpre">
<input :id="'stv-list-new-titelpre-' + uuid" type="text" name="titelpre" v-model="formDataPerson['titelpre']" class="form-control" :disabled="person">
</fhc-form-validation>
<!-- TODO(chris): more details -->
<table class="table caption-top table-striped table-hover">
<caption>Prüfung ob Person bereits existiert</caption>
<tbody>
<tr
v-for="(suggestion, index) in suggestions"
:key="suggestion.person_id"
:class="{'active': index == 2}"
@click="(index == 2) ? suggestions.shift() : person=suggestion"
v-accessibility:tab.vertical
>
<td>{{suggestion.vorname + ' ' + suggestion.nachname}}</td>
<td></td>
</tr>
</tbody>
</table>
</template>
<tempalte v-else>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-anrede-' + uuid">Anrede</label>
<fhc-form-validation name="anrede">
<input :id="'stv-list-new-anrede-' + uuid" type="text" name="anrede" v-model="formDataPerson['anrede']" class="form-control" :disabled="person">
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-titelpre-' + uuid">Titel (Pre)</label>
<fhc-form-validation name="titelpre">
<input :id="'stv-list-new-titelpre-' + uuid" type="text" name="titelpre" v-model="formDataPerson['titelpre']" class="form-control" :disabled="person">
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-titelpost-' + uuid">Titel (Post)</label>
<fhc-form-validation name="titelpost">
<input :id="'stv-list-new-titelpost-' + uuid" type="text" name="titelpost" v-model="formDataPerson['titelpost']" class="form-control" :disabled="person">
</fhc-form-validation>
</div>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-titelpost-' + uuid">Titel (Post)</label>
<fhc-form-validation name="titelpost">
<input :id="'stv-list-new-titelpost-' + uuid" type="text" name="titelpost" v-model="formDataPerson['titelpost']" class="form-control" :disabled="person">
</fhc-form-validation>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-nachname-' + uuid">Nachname*</label>
<fhc-form-validation name="nachname">
<input :id="'stv-list-new-nachname-' + uuid" type="text" name="nachname" v-model="formDataPerson['nachname']" class="form-control" :disabled="person" @input="loadSuggestions">
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-vorname-' + uuid">Vorname</label>
<fhc-form-validation name="vorname">
<input :id="'stv-list-new-vorname-' + uuid" type="text" name="vorname" v-model="formDataPerson['vorname']" class="form-control" :disabled="person" @input="loadSuggestions">
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-vornamen-' + uuid">Weitere Vornamen</label>
<fhc-form-validation name="vornamen">
<input :id="'stv-list-new-vornamen-' + uuid" type="text" name="vornamen" v-model="formDataPerson['vornamen']" class="form-control" :disabled="person">
</fhc-form-validation>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-nachname-' + uuid">Nachname*</label>
<fhc-form-validation name="nachname">
<input :id="'stv-list-new-nachname-' + uuid" type="text" name="nachname" v-model="formDataPerson['nachname']" class="form-control" :disabled="person" @input="loadSuggestions">
</fhc-form-validation>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-wahlname-' + uuid">Wahlname</label>
<fhc-form-validation name="wahlname">
<input :id="'stv-list-new-wahlname-' + uuid" type="text" name="wahlname" v-model="formDataPerson['wahlname']" class="form-control" :disabled="person">
</fhc-form-validation>
</div>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-vorname-' + uuid">Vorname</label>
<fhc-form-validation name="vorname">
<input :id="'stv-list-new-vorname-' + uuid" type="text" name="vorname" v-model="formDataPerson['vorname']" class="form-control" :disabled="person" @input="loadSuggestions">
</fhc-form-validation>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-geschlecht-' + uuid">Geschlecht*</label>
<fhc-form-validation name="geschlecht">
<select :id="'stv-list-new-geschlecht-' + uuid" class="form-control" class="form-select" :disabled="person" name="geschlecht" v-model="formDataPerson['geschlecht']">
<option v-for="geschlecht in lists.geschlechter" :key="geschlecht.geschlecht" :value="geschlecht.geschlecht">{{geschlecht.bezeichnung}}</option>
</select>
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'dp-input-stv-list-new-gebdatum-' + uuid">Geburtsdatum</label>
<fhc-form-validation name="gebdatum">
<vue-date-picker :uid="'stv-list-new-gebdatum-' + uuid" name="gebdatum" text-input auto-apply no-today v-model="formDataPerson['gebdatum']" :enable-time-picker="false" format="dd.MM.yyyy" @update:model-value="loadSuggestions" :disabled="person"></vue-date-picker>
</fhc-form-validation>
</div>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-vornamen-' + uuid">Weitere Vornamen</label>
<fhc-form-validation name="vornamen">
<input :id="'stv-list-new-vornamen-' + uuid" type="text" name="vornamen" v-model="formDataPerson['vornamen']" class="form-control" :disabled="person">
</fhc-form-validation>
<div v-if="person" class="row">
<div class="col-sm-6 mb-3">
<fhc-form-validation name="address[func]">
<select :id="'stv-list-new-address-func-' + uuid" name="address[func]" class="form-select" v-model="formData['address']['func']">
<option value="-1">Bestehende Adresse überschreiben</option>
<option value="1">Adresse hinzufügen</option>
<option value="0">Adresse nicht anlegen</option>
</select>
</fhc-form-validation>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-wahlname-' + uuid">Wahlname</label>
<fhc-form-validation name="wahlname">
<input :id="'stv-list-new-wahlname-' + uuid" type="text" name="wahlname" v-model="formDataPerson['wahlname']" class="form-control" :disabled="person">
</fhc-form-validation>
<fieldset v-if="!person || formData['address']['func']">
<legend>Adresse</legend>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'dp-input-stv-list-new-address-nation-' + uuid">Land</label>
<fhc-form-validation name="address.nation">
<select :id="'stv-list-new-address-nation' + uuid" name="address[nation]" class="form-select" v-model="formData['address']['nation']" @input="changeAddressNation">
<option v-for="nation in lists.nations" :key="nation.nation_code" :value="nation.nation_code" :disabled="nation.sperre">{{nation.langtext}}</option>
</select>
</fhc-form-validation>
</div>
</div>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'dp-input-stv-list-new-address-plz-' + uuid">PLZ</label>
<fhc-form-validation name="address[plz]">
<input type="text" :id="'stv-list-new-address-plz' + uuid" name="address[plz]" v-model="formData['address']['plz']" @input="loadPlaces">
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'dp-input-stv-list-new-address-gemeinde-' + uuid">Gemeinde</label>
<fhc-form-validation name="address[gemeinde]">
<select v-if="formData['address']['nation'] == 'A'" :id="'stv-list-new-address-gemeinde' + uuid" name="address[gemeinde]" class="form-select" v-model="formData['address']['gemeinde']">
<option v-if="!gemeinden.length" disabled>Bitte gültige PLZ wählen</option>
<option v-for="gemeinde in gemeinden" :key="gemeinde.name" :value="gemeinde.name">{{gemeinde.name}}</option>
</select>
<input v-else type="text" :id="'stv-list-new-address-gemeinde' + uuid" name="address[gemeinde]" class="form-control" v-model="formData['address']['gemeinde']">
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'dp-input-stv-list-new-address-ort-' + uuid">Ort</label>
<fhc-form-validation name="address[ort]">
<select v-if="formData['address']['nation'] == 'A'" :id="'stv-list-new-address-ort' + uuid" name="address[ort]" class="form-select" v-model="formData['address']['ort']">
<option v-if="!orte.length" disabled>Bitte gültige Gemeinde wählen</option>
<option v-for="ort in orte" :key="ort.ortschaftsname" :value="ort.ortschaftsname">{{ort.ortschaftsname}}</option>
</select>
<input v-else type="text" :id="'stv-list-new-address-ort' + uuid" name="address[ort]" class="form-control" v-model="formData['address']['ort']">
</fhc-form-validation>
</div>
</div>
<div class="row">
<div class="col-12 mb-3">
<label :for="'dp-input-stv-list-new-address-address-' + uuid">Adresse</label>
<fhc-form-validation name="address[address]">
<input type="text" :id="'stv-list-new-address-address' + uuid" name="address[address]" v-model="formData['address']['address']">
</fhc-form-validation>
</div>
</div>
</fieldset>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'dp-input-stv-list-new-geburtsnation-' + uuid">Geburtsnation</label>
<fhc-form-validation name="geburtsnation">
<select :id="'stv-list-new-geburtsnation' + uuid" name="geburtsnation" class="form-select" v-model="formData['geburtsnation']">
<option v-for="nation in lists.nations" :key="nation.nation_code" :value="nation.nation_code" :disabled="nation.sperre">{{nation.langtext}}</option>
</select>
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'dp-input-stv-list-new-staatsbuergerschaft-' + uuid">Staatsbürgerschaft</label>
<fhc-form-validation name="staatsbuergerschaft">
<select :id="'stv-list-new-staatsbuergerschaft' + uuid" name="staatsbuergerschaft" class="form-select" v-model="formData['staatsbuergerschaft']">
<option v-for="nation in lists.nations" :key="nation.nation_code" :value="nation.nation_code" :disabled="nation.sperre">{{nation.langtext}}</option>
</select>
</fhc-form-validation>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-geschlecht-' + uuid">Geschlecht*</label>
<fhc-form-validation name="geschlecht">
<select :id="'stv-list-new-geschlecht-' + uuid" class="form-control" :disabled="person" name="geschlecht" v-model="formDataPerson['geschlecht']">
<option v-for="geschlecht in geschlechter" :key="geschlecht.geschlecht" :value="geschlecht.geschlecht">{{geschlecht.bezeichnung}}</option>
</select>
</fhc-form-validation>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-email-' + uuid">E-Mail</label>
<fhc-form-validation name="email">
<input :id="'stv-list-new-email-' + uuid" type="text" name="email" v-model="formDataPerson['email']" class="form-control">
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-telefon-' + uuid">Telefon</label>
<fhc-form-validation name="telefon">
<input :id="'stv-list-new-telefon-' + uuid" type="text" name="telefon" v-model="formDataPerson['telefon']" class="form-control">
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-mobil-' + uuid">Mobil</label>
<fhc-form-validation name="mobil">
<input :id="'stv-list-new-mobil-' + uuid" type="text" name="mobil" v-model="formDataPerson['mobil']" class="form-control">
</fhc-form-validation>
</div>
</div>
<div class="col-sm-4 mb-3">
<label :for="'dp-input-stv-list-new-gebdatum-' + uuid">Geburtsdatum</label>
<fhc-form-validation name="gebdatum">
<vue-date-picker :uid="'stv-list-new-gebdatum-' + uuid" name="gebdatum" text-input auto-apply no-today v-model="formDataPerson['gebdatum']" :enable-time-picker="false" format="dd.MM.yyyy" @update:model-value="loadSuggestions" :disabled="person"></vue-date-picker>
</fhc-form-validation>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-letzteausbildung-' + uuid">Letzte Ausbildung</label>
<fhc-form-validation name="letzteausbildung">
<select :id="'stv-list-new-letzteausbildung' + uuid" name="letzteausbildung" class="form-select" v-model="formData['letzteausbildung']">
<option v-for="ausbildung in lists.ausbildungen" :key="ausbildung.ausbildungcode" :value="ausbildung.ausbildungcode">{{ausbildung.ausbildungbez}}</option>
</select>
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-ausbildungsart-' + uuid">Ausbildungsart</label>
<fhc-form-validation name="ausbildungsart">
<input :id="'stv-list-new-ausbildungsart-' + uuid" type="text" name="ausbildungsart" v-model="formDataPerson['ausbildungsart']" class="form-control">
</fhc-form-validation>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-8 mb-3">
<label :for="'stv-list-new-anmerkungen-' + uuid">Anmerkungen</label>
<fhc-form-validation name="anmerkungen">
<textarea :id="'stv-list-new-anmerkungen-' + uuid" name="anmerkungen" v-model="formDataPerson['anmerkungen']" class="form-control"></textarea>
</fhc-form-validation>
</div>
</div>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-studiengang_kz-' + uuid">Studiengang*</label>
<fhc-form-validation name="studiengang_kz">
<select :id="'stv-list-new-studiengang_kz-' + uuid" name="studiengang_kz" v-model="formDataStg" class="form-select">
<option v-for="stg in lists.stgs" :key="stg.studiengang_kz" :value="stg.studiengang_kz">{{stg.kuerzel}}</option>
</select>
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-studiensemester_kurzbz-' + uuid">Studiensemester*</label>
<fhc-form-validation name="studiensemester_kurzbz">
<select :id="'stv-list-new-studiensemester_kurzbz-' + uuid" name="studiensemester_kurzbz" v-model="formDataSem" class="form-select">
<option v-for="sem in semester" :key="sem.studiensemester_kurzbz" :value="sem.studiensemester_kurzbz">{{sem.studiensemester_kurzbz}}</option>
</select>
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-ausbildungssemester-' + uuid">Ausbildungssemester*</label>
<fhc-form-validation name="ausbildungssemester">
<select :id="'stv-list-new-ausbildungssemester-' + uuid" name="ausbildungssemester" v-model="formData['ausbildungssemester']" class="form-select" @input="loadStudienplaene" :disabled="formData['incoming']">
<option v-for="sem in Array.from({length:8}).map((u,i) => i+1)" :key="sem" :value="sem">{{sem}}. Semester</option>
</select>
</fhc-form-validation>
</div>
</div>
<div class="row">
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-orgform_kurzbz-' + uuid">OrgForm</label>
<fhc-form-validation name="orgform_kurzbz">
<select :id="'stv-list-new-orgform_kurzbz-' + uuid" name="orgform_kurzbz" v-model="formData['orgform_kurzbz']" class="form-select" @input="loadStudienplaene">
<option value="">-- keine Auswahl --</option>
<option v-for="orgform in lists.orgforms" :key="orgform.orgform_kurzbz" :value="orgform.orgform_kurzbz">{{orgform.bezeichnung}}</option>
</select>
</fhc-form-validation>
</div>
<div class="col-sm-4 mb-3">
<label :for="'stv-list-new-studienplan_id-' + uuid">Studienplan</label>
<fhc-form-validation name="studienplan_id">
<select :id="'stv-list-new-studienplan_id-' + uuid" name="studienplan_id" v-model="formData['studienplan_id']" class="form-select">
<option value="">-- keine Auswahl --</option>
<option v-for="plan in studienplaene" :key="plan.studienplan_id" :value="plan.studienplan_id">{{plan.bezeichnung}}</option>
</select>
</fhc-form-validation>
</div>
</div>
<div class="row">
<div class="col-10 mb-3">
<div class="form-check">
<fhc-form-validation name="incoming">
<input type="checkbox" :id="'stv-list-new-incoming-' + uuid" name="incoming" v-model="formData['incoming']" class="form-check-input" value="1">
</fhc-form-validation>
<label :for="'stv-list-new-incoming-' + uuid" class="form-check-label">Incoming</label>
</div>
</div>
</div>
</template>
</template>
<template #footer>
<div class="btn-group dropup">
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" style="border-bottom-right-radius: 0; border-top-right-radius: 0" data-bs-toggle="dropdown" aria-expanded="false">
<span class="visually-hidden">Choose Person</span>
</button>
<ul class="dropdown-menu">
<!-- TODO(chris): more details -->
<li v-for="suggestion in suggestions" :key="suggestion.person_id"><a class="dropdown-item" :class="{active: person?.person_id == suggestion.person_id}" href="#" @click.prevent="person=suggestion">{{suggestion.vorname + ' ' + suggestion.nachname}}</a></li>
<li><a class="dropdown-item" :class="{active: person === 0}" href="#" @click.prevent="person=0">Neue Person anlegen</a></li>
</ul>
<button type="submit" class="btn btn-primary" :disabled="person === null">{{saveTitle}}</button>
</div>
<button v-if="person !== null" type="button" class="btn btn-secondary" @click="person = null"><i class="fa fa-chevron-left"></i>Zurück</button>
<button type="submit" class="btn btn-primary">{{ person === null ? 'Person anlegen' : 'InteressentIn anlegen' }}</button>
</template>
</bs-modal>
</form>`
@@ -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: `
<div class="stv-studiensemester">
+26 -32
View File
@@ -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;
}
}
}
+22 -2
View File
@@ -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;