Details Person

This commit is contained in:
cgfhtw
2023-09-27 09:16:42 +02:00
parent bd92777b96
commit 9eeaeb2a14
8 changed files with 409 additions and 66 deletions
@@ -0,0 +1,94 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Student extends FHC_Controller
{
public function __construct()
{
// TODO(chris): access!
parent::__construct();
}
public function getPerson($person_id)
{
$this->load->model('person/Person_model', 'PersonModel');
$result = $this->PersonModel->load($person_id);
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(current(getData($result)));
}
}
public function getStudent($student_uid)
{
// TODO(chris): this is wrong
$this->load->model('crm/Student_model', 'StudentModel');
$result = $this->StudentModel->load([$student_uid]);
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(current(getData($result)));
}
}
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(getError($result));
} else {
$this->outputJson(getData($result) ?: []);
}
}
}
+2 -1
View File
@@ -10,7 +10,8 @@
'tabulator5' => true,
'phrases' => [],
'customCSSs' => [
'public/css/Studentenverwaltung.css'
'public/css/Studentenverwaltung.css',
'public/css/components/vue-datepicker.css'
],
'customJSModules' => [
'public/js/apps/Studentenverwaltung.js'
+25 -1
View File
@@ -26,6 +26,28 @@
"wiki": "https://wiki.fhcomplete.info/doku.php"
},
"repositories": [
{
"type": "package",
"package": {
"name": "vuepic/vue-datepicker-js",
"version": "4.0.0",
"dist": {
"url": "https://unpkg.com/@vuepic/vue-datepicker@4.0.0/dist/vue-datepicker.iife.js",
"type": "file"
}
}
},
{
"type": "package",
"package": {
"name": "vuepic/vue-datepicker-css",
"version": "4.0.0",
"dist": {
"url": "https://unpkg.com/@vuepic/vue-datepicker@4.0.0/dist/main.css",
"type": "file"
}
}
},
{
"type": "package",
"package": {
@@ -420,7 +442,9 @@
"twbs/bootstrap5": "5.1.*",
"vuejs/vuejs3": "3.2.33",
"vuejs/vuerouter4": "4.1.3"
"vuejs/vuerouter4": "4.1.3",
"vuepic/vue-datepicker-js": "4.*",
"vuepic/vue-datepicker-css": "4.*"
},
"config": {
"bin-dir": "vendor/bin"
+2
View File
@@ -0,0 +1,2 @@
@import '../../../vendor/vuepic/vue-datepicker-css/main.css';
+62
View File
@@ -0,0 +1,62 @@
export default {
emits: [
'update:modelValue'
],
props: {
modelValue: String
},
computed: {
valueAsBase64DataString() {
if (!this.modelValue || this.modelValue.substring(0, 10) == 'data:image')
return this.modelValue;
return 'data:image/jpeg;charset=utf-8;base64,' + this.modelValue;
}
},
methods: {
openUploadDialog() {
this.$refs.fileInput.click();
},
pickFile() {
let file = this.$refs.fileInput.files;
if (file && file[0]) {
let reader = new FileReader();
reader.onload = e => {
this.$emit('update:modelValue', e.target.result);
}
reader.readAsDataURL(file[0]);
}
},
deleteImage() {
this.$emit('update:modelValue', '');
}
},
template: `
<div class="form-upload-image">
<template v-if="modelValue">
<img class="img-thumbnail" :src="valueAsBase64DataString" />
<div class="fotobutton">
<div class="d-grid gap-2 d-md-flex">
<button type="button" class="btn btn-outline-dark btn-sm" @click="deleteImage">
<i class="fa fa-close"></i>
</button>
<button type="button" class="btn btn-outline-dark btn-sm" @click="openUploadDialog">
<i class="fa fa-pen"></i>
</button>
</div>
</div>
</template>
<template v-else>
<slot #placeholder>
<svg class="bd-placeholder-img img-thumbnail" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="A generic square placeholder image with a white border around it, making it resemble a photograph taken with an old instant camera: 200x200" preserveAspectRatio="xMidYMid slice" focusable="false"><title>A generic square placeholder image with a white border around it, making it resemble a photograph taken with an old instant camera</title><rect width="100%" height="100%" fill="#868e96"></rect><text x="50%" y="50%" fill="#dee2e6" dy=".3em"></text></svg>
<div class="fotobutton-visible">
<div class="d-grid gap-2 d-md-flex">
<button type="button" class="btn btn-outline-dark btn-sm" @click="openUploadDialog">
<i class="fa fa-pen"></i>
</button>
</div>
</div>
</slot>
</template>
<input class="d-none" type="file" ref="fileInput" @input="pickFile" accept="image/*">
</div>`
}
@@ -1,86 +1,235 @@
import VueDatePicker from '../../../vueDatepicker.js.php';
import FormUploadImage from '../../../Form/Upload/Image.js';
import {CoreRESTClient} from '../../../../RESTClient.js';
export default {
components: {
VueDatePicker,
FormUploadImage
},
props: {
student: Object
},
data() {
return {
person_id: '',
bpk: '',
anrede: '',
titelpre: '',
titelpost: '',
nachname: '',
vorname: '',
vornamen: '',
wahlname: '',
gebdatum: '',
gebort: '',
gebnation: ''
nations: [],
sprachen: [],
geschlechter: [],
familienstaende: {
"": "--keine Auswahl--",
"g": "geschieden",
"l": "ledig",
"v": "verheiratet",
"w": "verwitwet"
},
person: null,
studentIn: null
}
},
watch: {
student(n) {
this.person_id = n.person_id;
this.bpk = n.bpk;
this.anrede = n.anrede;
this.titelpre = n.titelpre;
this.titelpost = n.titelpost;
this.nachname = n.nachname;
this.vorname = n.vorname;
this.vornamen = n.vornamen;
this.wahlname = n.wahlname;
this.gebdatum = n.gebdatum;
// TODO(chris): gebdatum > datepicker
// TODO(chris): gebort & getnation?
CoreRESTClient
.get('components/stv/Student/getPerson/' + this.student.person_id)
.then(result => result.data)
.then(result => {
this.person = result;
if (!this.person.familienstand)
this.person.familienstand = '';
})
.catch(err => {
console.error(err.response.data || err.message);
});
CoreRESTClient
.get('components/stv/Student/getStudent/' + this.student.uid)
.then(result => result.data)
.then(result => {
// TODO(chris): IMPLEMENT HERE!
console.log(result);
this.studentIn = result;
})
.catch(err => {
console.error(err.response.data || err.message);
});
}
},
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 => {
this.geschlechter = result.data;
})
.catch(err => {
console.error(err.response.data || err.message);
});
},
template: `
<div class="stv-details-details h-100 pb-3">
<fieldset>
<legend>Person</legend>
<div class="row mb-3">
<label for="stv-details-person_id" class="col-sm-1 col-form-label">Person ID</label>
<div class="col-sm-3">
<input id="stv-details-person_id" type="text" class="form-control" v-model="person_id">
<template v-if="person">
<div class="row mb-3">
<label for="stv-details-person_id" class="col-sm-1 col-form-label">Person ID</label>
<div class="col-sm-3">
<input id="stv-details-person_id" type="text" class="form-control" v-model="person.person_id">
</div>
<label for="stv-details-bpk" class="col-sm-1 col-form-label">BPK</label>
<div class="col-sm-3">
<input id="stv-details-bpk" type="text" class="form-control" v-model="person.bpk">
</div>
</div>
<label for="stv-details-bpk" class="col-sm-1 col-form-label">BPK</label>
<div class="col-sm-3">
<input id="stv-details-bpk" type="text" class="form-control" v-model="bpk">
<div class="row mb-3">
<label for="stv-details-anrede" class="col-sm-1 col-form-label">Anrede</label>
<div class="col-sm-3">
<input id="stv-details-anrede" type="text" class="form-control" v-model="person.anrede">
</div>
<label for="stv-details-titelpre" class="col-sm-1 col-form-label">Titel Pre</label>
<div class="col-sm-3">
<input id="stv-details-titelpre" type="text" class="form-control" v-model="person.titelpre">
</div>
<label for="stv-details-titelpost" class="col-sm-1 col-form-label">Titel Post</label>
<div class="col-sm-3">
<input id="stv-details-titelpost" type="text" class="form-control" v-model="person.titelpost">
</div>
</div>
<div class="row mb-3">
<label for="stv-details-nachname" class="col-sm-1 col-form-label">Nachname</label>
<div class="col-sm-3">
<input id="stv-details-nachname" type="text" class="form-control" v-model="person.nachname">
</div>
<label for="stv-details-vorname" class="col-sm-1 col-form-label">Vorname</label>
<div class="col-sm-3">
<input id="stv-details-vorname" type="text" class="form-control" v-model="person.vorname">
</div>
<label for="stv-details-vornamen" class="col-sm-1 col-form-label">Vornamen</label>
<div class="col-sm-3">
<input id="stv-details-vornamen" type="text" class="form-control" v-model="person.vornamen">
</div>
</div>
<div class="row mb-3">
<label for="stv-details-wahlname" class="col-sm-1 col-form-label">Wahlname</label>
<div class="col-sm-3">
<input id="stv-details-wahlname" type="text" class="form-control" v-model="person.wahlname">
</div>
</div>
<div class="row mb-3">
<label for="dp-input-stv-details-gebdatum" class="col-sm-1 col-form-label">Geburtsdatum</label>
<div class="col-sm-3">
<vue-date-picker uid="stv-details-gebdatum" v-model="person.gebdatum" :clearable="false" no-today auto-apply :enable-time-picker="false" format="dd.MM.yyyy" preview-format="dd.MM.yyyy"></vue-date-picker>
</div>
<label for="stv-details-gebort" class="col-sm-1 col-form-label">Geburtsort</label>
<div class="col-sm-3">
<input id="stv-details-gebort" type="text" class="form-control" v-model="person.gebort">
</div>
<label for="stv-details-geburtsnation" class="col-sm-1 col-form-label">Geburtsnation</label>
<div class="col-sm-3">
<select id="stv-details-geburtsnation" class="form-control" v-model="person.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>
</select>
</div>
</div>
<div class="row mb-3">
<label for="stv-details-svnr" class="col-sm-1 col-form-label">SVNR</label>
<div class="col-sm-3">
<input id="stv-details-svnr" type="text" class="form-control" v-model="person.svnr">
</div>
<label for="stv-details-ersatzkennzeichen" class="col-sm-1 col-form-label">Ersatzkennzeichen</label>
<div class="col-sm-3">
<input id="stv-details-ersatzkennzeichen" type="text" class="form-control" v-model="person.ersatzkennzeichen">
</div>
</div>
<div class="row mb-3">
<label for="stv-details-staatsbuergerschaft" class="col-sm-1 col-form-label">Staatsbürgerschaft</label>
<div class="col-sm-3">
<select id="stv-details-staatsbuergerschaft" class="form-control" v-model="person.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>
</select>
</div>
<label for="stv-details-matr_nr" class="col-sm-1 col-form-label">Matrikelnummer</label>
<div class="col-sm-3">
<input id="stv-details-matr_nr" type="text" class="form-control" v-model="person.matr_nr">
</div>
<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="person.sprache">
<option v-for="sprache in sprachen" :key="sprache.sprache" :value="sprache.sprache">{{sprache.sprache}}</option>
</select>
</div>
</div>
<div class="row mb-3">
<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="person.geschlecht">
<option v-for="geschlecht in 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>
<div class="col-sm-3">
<select id="stv-details-familienstand" class="form-control" v-model="person.familienstand">
<option v-for="(bezeichnung, key) in familienstaende" :key="key" :value="key">{{bezeichnung}}</option>
</select>
</div>
</div>
<div class="row mb-3">
<label for="stv-details-foto" class="col-sm-1 col-form-label">Foto</label>
<div class="col-sm-3">
<form-upload-image id="stv-details-foto" v-model="person.foto"></form-upload-image>
</div>
<label for="stv-details-anmerkung" class="col-sm-1 col-form-label">Anmerkung</label>
<div class="col-sm-3">
<textarea id="stv-details-anmerkung" class="form-control" v-text="anmerkung"></textarea>
</div>
<label for="stv-details-homepage" class="col-sm-1 col-form-label">Homepage</label>
<div class="col-sm-3">
<input id="stv-details-homepage" type="text" class="form-control" v-model="person.homepage">
</div>
</div>
</template>
<div v-else>
Loading...
</div>
<div class="row mb-3">
<label for="stv-details-anrede" class="col-sm-1 col-form-label">Anrede</label>
<div class="col-sm-3">
<input id="stv-details-anrede" type="text" class="form-control" v-model="anrede">
</div>
<label for="stv-details-titelpre" class="col-sm-1 col-form-label">Titel Pre</label>
<div class="col-sm-3">
<input id="stv-details-titelpre" type="text" class="form-control" v-model="titelpre">
</div>
<label for="stv-details-titelpost" class="col-sm-1 col-form-label">Titel Post</label>
<div class="col-sm-3">
<input id="stv-details-titelpost" type="text" class="form-control" v-model="titelpost">
</div>
</div>
<div class="row mb-3">
<label for="stv-details-wahlname" class="col-sm-1 col-form-label">Wahlname</label>
<div class="col-sm-3">
<input id="stv-details-wahlname" type="text" class="form-control" v-model="wahlname">
</div>
</div>
<div class="row mb-3">
<label for="stv-details-gebdatum" class="col-sm-1 col-form-label">Geburtsdatum</label>
<div class="col-sm-3">
<input id="stv-details-gebdatum" type="text" class="form-control" v-model="gebdatum">
</div>
<label for="stv-details-gebort" class="col-sm-1 col-form-label">Geburtsort</label>
<div class="col-sm-3">
<input id="stv-details-gebort" type="text" class="form-control" v-model="gebort">
</div>
<label for="stv-details-gebnation" class="col-sm-1 col-form-label">Geburtsnation</label>
<div class="col-sm-3">
<input id="stv-details-gebnation" type="text" class="form-control" v-model="gebnation">
</fieldset>
<fieldset>
<legend>StudentIn</legend>
<template v-if="studentIn">
<div class="row mb-3">
<label for="stv-details-student_uid" class="col-sm-1 col-form-label">UID</label>
<div class="col-sm-3">
<input id="stv-details-student_uid" type="text" class="form-control" v-model="studentIn.student_uid">
</div>
<label for="stv-details-personenkennzeichen" class="col-sm-1 col-form-label">Personenkennzeichen</label>
<div class="col-sm-3">
<input id="stv-details-personenkennzeichen" type="text" class="form-control" v-model="studentIn.personenkennzeichen">
</div>
<label for="stv-details-aktiv" class="col-sm-1 col-form-label">Aktiv</label>
<div class="col-sm-3">
<div class="form-check">
<input id="stv-details-aktiv" type="checkbox" class="form-check-input" v-model="studentIn.aktiv">
</div>
</div>
</div>
</template>
<div v-else>
Loading...
</div>
</fieldset>
</div>`
@@ -81,7 +81,6 @@ export default {
this.$refs.table.tabulator.on("dataProcessed", () => {
let rows = this.$refs.table.tabulator.getRows();
if (rows.length && rows.length == 1) {
console.log();
this.$refs.table.tabulator.selectRow();
}
});
+12
View File
@@ -0,0 +1,12 @@
<?php
if(file_exists("../../../vendor/vuepic/vue-datepicker-js/vue-datepicker.iife.js"))
{
header('Content-Type: application/javascript');
echo file_get_contents("../../../vendor/vuepic/vue-datepicker-js/vue-datepicker.iife.js");
echo "export default VueDatePicker";
}
else
{
header('HTTP/1.0 404 Not Found');
}