FhcAlert improvements & InteressentIn anlegen part 1

This commit is contained in:
cgfhtw
2023-11-06 11:06:10 +01:00
parent 45715d78f7
commit 52d406bca7
9 changed files with 325 additions and 27 deletions
@@ -68,6 +68,7 @@ class Verband extends FHC_Controller
$this->StudiengangModel->addSelect('typ');
$this->StudiengangModel->addSelect('kurzbz');
$this->StudiengangModel->addSelect('studiengang_kz');
$this->StudiengangModel->addSelect('studiengang_kz AS stg_kz');
$this->StudiengangModel->addOrder('erhalter_kz');
$this->StudiengangModel->addOrder('typ');
@@ -123,6 +124,7 @@ class Verband extends FHC_Controller
$this->StudiengangModel->addSelect("CONCAT(UPPER(CONCAT(typ, kurzbz)), '-', semester, (SELECT CASE WHEN bezeichnung IS NULL OR bezeichnung='' THEN ''::TEXT ELSE CONCAT(' (', bezeichnung, ')') END FROM public.tbl_lehrverband WHERE studiengang_kz=v.studiengang_kz AND semester=v.semester ORDER BY verband, gruppe LIMIT 1)) AS name", false);
$this->StudiengangModel->addSelect('semester');
$this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . ' AS stg_kz', false);
$this->StudiengangModel->addOrder('semester');
@@ -146,7 +148,7 @@ class Verband extends FHC_Controller
array_unshift($list, [
'name' => 'PreStudent',
'link' => $link . 'prestudent',
'children' => $this->getStdSem($link . 'prestudent/')
'children' => $this->getStdSem($link . 'prestudent/', $studiengang_kz)
]);
if ($org_form === null) {
@@ -211,6 +213,7 @@ class Verband extends FHC_Controller
$this->GruppeModel->addSelect('sort');
$this->GruppeModel->addSelect('gruppe_kurzbz');
$this->GruppeModel->addSelect($this->GruppeModel->escape($studiengang_kz) . ' AS stg_kz', false);
$this->GruppeModel->addOrder('sort');
$this->GruppeModel->addOrder('gruppe_kurzbz');
@@ -243,6 +246,7 @@ class Verband extends FHC_Controller
$this->StudiengangModel->addSelect("CASE WHEN MAX(gruppe)='' OR MAX(gruppe)=' ' THEN TRUE ELSE FALSE END AS leaf");
$this->StudiengangModel->addSelect('verband');
$this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . ' AS stg_kz', false);
$this->StudiengangModel->addOrder('verband');
@@ -293,6 +297,7 @@ class Verband extends FHC_Controller
$this->StudiengangModel->addSelect("TRUE AS leaf", false);
$this->StudiengangModel->addSelect('gruppe');
$this->StudiengangModel->addSelect($this->StudiengangModel->escape($studiengang_kz) . ' AS stg_kz', false);
$this->StudiengangModel->addOrder('gruppe');
@@ -320,10 +325,11 @@ class Verband extends FHC_Controller
/**
* @param string $link
* @param integer $studiengang_kz
*
* @return array
*/
protected function getStdSem($link)
protected function getStdSem($link, $studiengang_kz)
{
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
@@ -350,29 +356,35 @@ class Verband extends FHC_Controller
$result[] = [
'name' => $sem->studiensemester_kurzbz,
'link' => $semlink,
'stg_kz' => $studiengang_kz,
'children' => [
[
'name' => 'Interessenten',
'link' => $intlink,
'stg_kz' => $studiengang_kz,
'children' => [
[
'name' => 'Bewerbung nicht abgeschickt',
'link' => $intlink . '/bewerbungnichtabgeschickt',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Bewerbung abgeschickt, Status unbestätigt',
'link' => $intlink . '/bewerbungabgeschickt',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'ZGV erfüllt',
'link' => $intlink . '/zgv',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Status bestätigt',
'link' => $intlink . '/statusbestaetigt',
'stg_kz' => $studiengang_kz,
'children' => [
[
'name' => 'Nicht zum Reihungstest angemeldet',
@@ -389,11 +401,13 @@ class Verband extends FHC_Controller
[
'name' => 'Nicht zum Reihungstest angemeldet',
'link' => $intlink . '/reihungstestnichtangemeldet',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Reihungstest angemeldet',
'link' => $intlink . '/reihungstestangemeldet',
'stg_kz' => $studiengang_kz,
'leaf' => true
]
]
@@ -401,26 +415,31 @@ class Verband extends FHC_Controller
[
'name' => 'Bewerber',
'link' => $semlink . '/bewerber',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Aufgenommen',
'link' => $semlink . '/aufgenommen',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Warteliste',
'link' => $semlink . '/warteliste',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Absage',
'link' => $semlink . '/absage',
'stg_kz' => $studiengang_kz,
'leaf' => true
],
[
'name' => 'Incoming',
'link' => $semlink . '/incoming',
'stg_kz' => $studiengang_kz,
'leaf' => true
]
]
+3 -3
View File
@@ -121,8 +121,8 @@ export const CoreRESTClient = {
*/
getError: function(response) {
if (typeof response[CORE_REST_CLIENT_RETVAL] === "object"
&& Object.keys(response[CORE_REST_CLIENT_RETVAL]).length > 0
if (typeof response === "object"
&& Object.keys(response).length > 0
&& response.hasOwnProperty(CORE_REST_CLIENT_RETVAL))
{
return response[CORE_REST_CLIENT_RETVAL];
@@ -136,7 +136,7 @@ export const CoreRESTClient = {
*/
getErrorCode: function(response) {
if (typeof response[CORE_REST_CLIENT_RETVAL] === "object" && response.hasOwnProperty(CORE_REST_CLIENT_ERROR))
if (typeof response === "object" && response.hasOwnProperty(CORE_REST_CLIENT_ERROR))
{
return response[CORE_REST_CLIENT_ERROR];
}
+69
View File
@@ -0,0 +1,69 @@
export default {
props: {
name: String
},
data() {
return {
isValid: false,
isInvalid: false,
invalidFeedback: ''
};
},
methods: {
reset() {
this.isValid = false;
this.isInvalid = false;
this.invalidFeedback = '';
},
setValid() {
this.isValid = true;
},
setInvalid(feedback) {
this.invalidFeedback = feedback?.detail || '';
this.isInvalid = true;
}
},
render() {
if (!this.$slots.default)
return Vue.h('div', {
'data-fhc-form-error': true,
class: {
'alert': true,
'alert-danger': true,
'd-none': !this.isInvalid
},
role: 'alert',
onFhcFormReset: this.reset,
onFhcFormError: this.setInvalid
}, (this.invalidFeedback || []).map((txt, i) => Vue.h('p', {
key: i,
class: i+1 == (this.invalidFeedback || []).length ? 'mb-0' : ''
}, txt)));
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,
class: {
'form-control': true,
'is-valid': this.isValid,
'is-invalid': this.isInvalid
}
};
if (orig.type.__name == 'VueDatePicker') {
options.class['p-0'] = true;
options.inputClassName = 'border-0';
}
res.unshift(Vue.cloneVNode(orig, options));
if (this.isInvalid && this.invalidFeedback && this.$slots.default)
res.push(Vue.h('div', {
class: 'invalid-feedback'
}, this.invalidFeedback));
return res;
},
};
@@ -80,6 +80,7 @@ export default {
}
}
},
studiengangKz: undefined,
}
},
computed: {
@@ -88,7 +89,8 @@ export default {
}
},
methods: {
onSelectVerband(link) {
onSelectVerband({link, studiengang_kz}) {
this.studiengangKz = studiengang_kz;
this.$refs.stvList.updateUrl(link);
},
searchfunction(searchsettings) {
@@ -124,7 +126,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"></stv-list>
<stv-list ref="stvList" v-model:selected="selected" :studiengang-kz="studiengangKz"></stv-list>
</template>
<template #bottom>
<stv-details :student="lastSelected"></stv-details>
@@ -187,11 +187,12 @@ export default {
});
CoreRESTClient
.get('components/stv/Student/getGeschlechter')
.then(result => CoreRESTClient.getData(result.data))
.then(result => {
this.geschlechter = result.data;
})
.catch(err => {
console.error(err.response.data || err.message);
console.error(CoreRestClient.getError(err.response.data) || err.message);
});
this.updateStudent(this.student);
},
@@ -1,12 +1,15 @@
import {CoreFilterCmpt} from "../../filter/Filter.js";
import {CoreRESTClient} from '../../../RESTClient.js';
import ListNew from './List/New.js';
export default {
components: {
CoreFilterCmpt
CoreFilterCmpt,
ListNew
},
props: {
selected: Array
selected: Array,
studiengangKz: Number
},
emits: [
'update:selected'
@@ -80,7 +83,7 @@ export default {
},
methods: {
actionNewPrestudent() {
console.log('actionNewPrestudent');
this.$refs.new.open();
},
rowSelectionChanged(data) {
this.$emit('update:selected', data);
@@ -172,10 +175,11 @@ export default {
:side-menu="false"
reload
new-btn-show
new-btn-label="Prestudent"
new-btn-label="InteressentIn"
@click:new="actionNewPrestudent"
tabindex="0"
>
</core-filter-cmpt>
<list-new ref="new" studiengang-kz="studiengangKz"></list-new>
</div>`
};
@@ -0,0 +1,209 @@
import {CoreRESTClient} from '../../../../RESTClient.js';
import BsModal from '../../../Bootstrap/Modal.js';
import FhcFormValidation from '../../../Form/Validation.js';
import VueDatePicker1 from '../../../vueDatepicker.js.php';
var _uuid = 0;
export default {
components: {
BsModal,
FhcFormValidation,
VueDatePicker1
},
props: {
studiengangKz: Number
},
data() {
return {
date: null,
geschlechter: []
}
},
methods: {
open() {
this.$refs.modal.show();
},
send(e) {
this.sendForm(e.target, 'components/stv/student/check')
.then(result => {
console.log('check: ', result);
});
},
sendForm(form, url) {
this.resetFormValidation(form);
const data = new FormData(form);
return CoreRESTClient
.post(url, data)
.then(result => result.data)
.then(result => {
if (CoreRESTClient.isError(result))
throw new Error(CoreRESTClient.getError(result));
return result;
})
.catch(this.handleErrors(form));
},
resetForm() {
const form = this.$refs.form;
form.reset();
this.resetFormValidation(form);
},
resetFormValidation(form) {
const event = new Event('fhc-form-reset');
form.querySelectorAll(['[data-fhc-form-validate],[data-fhc-form-error]']).forEach(el => el.dispatchEvent(event));
/*const alert = form.querySelector('div.alert.alert-danger[role="alert"]');
if (alert) {
alert.innerHTML = '';
alert.classList.add('d-none');
}
form.querySelectorAll('.invalid-feedback').forEach(n => n.remove());
form.querySelectorAll('.is-invalid').forEach(n => n.classList.remove('is-invalid'));
form.querySelectorAll('.is-valid').forEach(n => n.classList.remove('is-valid'));*/
},
handleErrors(error, form) {
if (form === undefined) {
if (error && error.nodeType === Node.ELEMENT_NODE)
return err => this.handleErrors(err, error);
} else {
if (error?.response?.status == 400) {
let errors = CoreRESTClient.getError(error.response.data);
if (typeof errors !== "object")
errors = error.response.data;
// NOTE(chris): reset form validation
this.resetFormValidation(form);
// NOTE(chris): set form input validation
const notFound = Object.entries(errors).filter(([key, detail]) => {
const input = form.querySelector('[data-fhc-form-validate="' + key + '"]');
if (!input)
return true;
input.dispatchEvent(new CustomEvent('fhc-form-invalidate', {detail}));
/*const input = form.querySelector('[name="' + key + '"]');
if (!input)
return true;
input.classList.add('is-invalid');
const feedback = document.createElement('div');
feedback.classList.add('invalid-feedback');
feedback.innerHTML = detail;
input.after(feedback);*/
return false;
}).map(arr => arr[1]);
//const alert = form.querySelector('div.alert.alert-danger[role="alert"]');
const alert = form.querySelector('[data-fhc-form-error]');
if (alert && notFound.length) {
alert.dispatchEvent(new CustomEvent('fhc-form-error', {detail: notFound}));
/*notFound.forEach(txt => {
const p = document.createElement('p');
p.innerHTML = txt;
alert.append(p);
});
if (notFound.length) {
alert.lastChild.classList.add('mb-0');
alert.classList.remove('d-none');
}*/
} else {
notFound.forEach(this.$fhcAlert.alertError);
}
return;
}
}
this.$fhcAlert.handleSystemError(error);
},test() {console.log('test')}
},
created() {
this.uuid = _uuid++;
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);
});
},
template: `
<form ref="form" class="stv-list-new" @submit.prevent="send">
<bs-modal ref="modal" dialog-class="modal-fullscreen" @hidden-bs-modal="resetForm">
<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" class="form-control">
</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" class="form-control">
</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" class="form-control">
</fhc-form-validation>
</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" class="form-control">
</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" class="form-control">
</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" class="form-control">
</fhc-form-validation>
</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" class="form-control">
</fhc-form-validation>
</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" name="geschlecht">
<option v-for="geschlecht in 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-picker1 :uid="'stv-list-new-gebdatum-' + uuid" name="gebdatum" text-input auto-apply no-today v-model="date" :enable-time-picker="false" format="dd.MM.yyyy"></vue-date-picker1>
</fhc-form-validation>
</div>
</div>
</template>
<template #footer>
<button type="submit" class="btn btn-primary">Vorschläge laden</button>
</template>
</bs-modal>
</form>`
};
@@ -77,15 +77,13 @@ export default {
this.loading = false;
})
.catch(error => {
console.error(error);
});
.catch(this.$fhcAlert.handleSystemError);
}
}
},
onSelectTreeNode(node) {
if (node.data.link)
this.$emit('selectVerband', 'components/stv/students/' + node.data.link);
this.$emit('selectVerband', {link: 'components/stv/students/' + node.data.link, studiengang_kz: node.data.stg_kz});
},
mapResultToTreeData(el) {
const cp = {
@@ -180,9 +178,7 @@ export default {
this.nodes = result.map(this.mapResultToTreeData);
this.loading = false;
})
.catch(error => {
console.error(error);
});
.catch(this.$fhcAlert.handleSystemError);
CoreRESTClient
.get("components/stv/favorites")
.then(result => result.data)
@@ -200,9 +196,7 @@ export default {
this.favorites = f;
}
})
.catch(error => {
console.error(error);
});
.catch(this.$fhcAlert.handleSystemError);
},
template: `
<div class="overflow-auto" tabindex="-1">
+5 -5
View File
@@ -123,8 +123,8 @@ const helperApp = Vue.createApp({
return "mailto:" + mailTo + "?subject=" + subject + "&body=" + body;
},
openMessagecard() {
bootstrap.Collapse.getOrCreateInstance(this.$refs.messageCard).toggle();
openMessagecard(e) {
bootstrap.Collapse.getOrCreateInstance(e.target.getAttribute('href')).toggle();
}
},
unmounted() {
@@ -142,10 +142,10 @@ const helperApp = Vue.createApp({
<a
class="align-bottom flex-fill me-2"
data-bs-toggle="collapse"
href="#collapseMessageCard"
:href="'#fhcAlertCollapseMessageCard' + slotProps.message.id"
role="button"
aria-expanded="false"
aria-controls="collapseMessageCard"
:aria-controls="'fhcAlertCollapseMessageCard' + slotProps.message.id"
@click="openMessagecard"
>
Fehler anzeigen
@@ -158,7 +158,7 @@ const helperApp = Vue.createApp({
Fehler melden
</a>
</div>
<div ref="messageCard" id="collapseMessageCard" class="collapse mt-3">
<div ref="messageCard" :id="'fhcAlertCollapseMessageCard' + slotProps.message.id" class="collapse mt-3">
<div class="card card-body text-body small" style="white-space: pre-wrap">
{{slotProps.message.detail}}
</div>