diff --git a/application/controllers/components/stv/Noten.php b/application/controllers/components/stv/Noten.php index dfde2892b..fb61de065 100644 --- a/application/controllers/components/stv/Noten.php +++ b/application/controllers/components/stv/Noten.php @@ -30,7 +30,7 @@ class Noten extends Auth_Controller return $this->outputJson($result); } - public function getZeugnis($prestudent_id) + public function getZeugnis($prestudent_id, $all = null) { $this->load->model('crm/Student_model', 'StudentModel'); $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); @@ -47,7 +47,7 @@ class Noten extends Auth_Controller $student_uid = current(getData($result))->student_uid; - $studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell'); + $studiensemester_kurzbz = ($all === null) ? $this->variablelib->getVar('semester_aktuell') : null; $result = $this->ZeugnisnoteModel->getZeugnisnoten($student_uid, $studiensemester_kurzbz); if (isError($result)) { diff --git a/application/controllers/components/stv/Student.php b/application/controllers/components/stv/Student.php index 88627ca03..ddfd95aed 100644 --- a/application/controllers/components/stv/Student.php +++ b/application/controllers/components/stv/Student.php @@ -77,6 +77,7 @@ class Student extends FHC_Controller $this->form_validation->set_rules('semester', 'Semester', 'integer'); if ($this->form_validation->run() == false) { + $this->output->set_status_header(REST_Controller::HTTP_BAD_REQUEST); return $this->outputJsonError($this->form_validation->error_array()); } @@ -202,7 +203,11 @@ class Student extends FHC_Controller } } - $this->outputJsonSuccess(true); + $this->outputJson(success(array_fill_keys(array_merge( + array_keys($update_lehrverband), + array_keys($update_person), + array_keys($update_student) + ), ''), 1)); } public function check() diff --git a/public/css/Fhc.css b/public/css/Fhc.css index 23c2379ea..1376a251f 100644 --- a/public/css/Fhc.css +++ b/public/css/Fhc.css @@ -2,82 +2,10 @@ white-space: pre-line; } -.accordion-button-primary { - background-color: #e7f1ff; - color: #0c63e4; -} -.accordion-button-primary:not(.collapsed) { - background-color: #cfe2ff; - color: #0a58ca; +.btn-p-0 { + padding: 0 .375rem; } -.accordion-button-secondary { - background-color: #f0f1f2; - color: #616971; +.z-1 { + z-index: 1; } -.accordion-button-secondary:not(.collapsed) { - background-color: #e2e3e5; - color: #565e64; -} - -.accordion-button-success { - background-color: #e8f3ee; - color: #177a4c; -} -.accordion-button-success:not(.collapsed) { - background-color: #d1e7dd; - color: #146c43; -} - -.accordion-button-info { - background-color: #e7fafe; - color: #0cb6d8; -} -.accordion-button-info:not(.collapsed) { - background-color: #cff4fc; - color: #0aa2c0; -} - -.accordion-button-warning { - background-color: #fff9e6; - color: #e6ae06; -} -.accordion-button-warning:not(.collapsed) { - background-color: #fff3cd; - color: #cc9a06; -} - -.accordion-button-danger { - background-color: #fcebec; - color: #c6303e; -} -.accordion-button-danger:not(.collapsed) { - background-color: #f8d7da; - color: #b02a37; -} - -.accordion-button-light { - background-color: #fefeff; - color: #dfe0e1; -} -.accordion-button-light:not(.collapsed) { - background-color: #fefefe; - color: #c6c7c8; -} - -.accordion-button-dark { - background-color: #e9e9ea; - color: #1e2125; -} -.accordion-button-dark:not(.collapsed) { - background-color: #d3d3d4; - color: #1a1e21; -} - -.tabulator-edit-list .tabulator-edit-list-item { - background-color: white; -} -.tabulator-edit-list .tabulator-edit-list-item:hover, -.tabulator-edit-list .tabulator-edit-list-item.active { - color: white; -} \ No newline at end of file diff --git a/public/css/Studentenverwaltung.css b/public/css/Studentenverwaltung.css index f845adc43..3f12660ff 100644 --- a/public/css/Studentenverwaltung.css +++ b/public/css/Studentenverwaltung.css @@ -1,3 +1,4 @@ +@import './Fhc.css'; @import './components/searchbar.css'; @import './components/verticalsplit.css'; @import './components/FilterComponent.css'; diff --git a/public/js/components/Form/Input.js b/public/js/components/Form/Input.js index 46ddbd3c5..8107c1a19 100644 --- a/public/js/components/Form/Input.js +++ b/public/js/components/Form/Input.js @@ -14,7 +14,8 @@ export default { bsFeedback: Boolean, noAutoClass: Boolean, type: String, - name: String + name: String, + containerClass: [String, Array, Object] }, data() { return { @@ -23,6 +24,13 @@ export default { } }, computed: { + hasContainer() { + if (!this.bsFeedback) + return true; + if (this.containerClass) + return true; + return false; + }, lcType() { if (!this.type) return 'text'; @@ -37,6 +45,8 @@ export default { return 'VueDatePicker'; case 'autocomplete': return 'PvAutocomplete'; + case 'uploadimage': + return 'UploadImage'; default: return 'input'; } @@ -133,7 +143,9 @@ export default { if (this.tag == 'VueDatePicker' && !this._.components.VueDatePicker) { this._.components.VueDatePicker = Vue.defineAsyncComponent(() => import("../vueDatepicker.js.php")); } else if (this.tag == 'PvAutocomplete' && !this._.components.PvAutocomplete) { - this._.components.PvAutocomplete = Vue.defineAsyncComponent(() => import(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + "/public/js/components/primevue/autocomplete/autocomplete.esm.min.js"));; + this._.components.PvAutocomplete = Vue.defineAsyncComponent(() => import(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router + "/public/js/components/primevue/autocomplete/autocomplete.esm.min.js")); + } else if (this.tag == 'UploadImage' && !this._.components.UploadImage) { + this._.components.UploadImage = Vue.defineAsyncComponent(() => import("./Upload/Image.js")); } } }, @@ -149,7 +161,7 @@ export default { // TODO(chris): wrap check in div? }, template: ` - + @@ -197,7 +209,7 @@ export default { > -
+
- +
` } \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Details.js b/public/js/components/Stv/Studentenverwaltung/Details/Details.js index ebbd68dd2..0c988179f 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Details.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Details.js @@ -1,16 +1,14 @@ -import VueDatePicker from '../../../vueDatepicker.js.php'; -import FormUploadImage from '../../../Form/Upload/Image.js'; import {CoreRESTClient} from '../../../../RESTClient.js'; - - -import PvToast from "../../../../../../index.ci.php/public/js/components/primevue/toast/toast.esm.min.js"; +import FormForm from '../../../Form/Form.js'; +import FormInput from '../../../Form/Input.js'; +import FormUploadImage from '../../../Form/Upload/Image.js'; export default { components: { - VueDatePicker, - FormUploadImage, - PvToast + FormForm, + FormInput, + FormUploadImage }, inject: { showBpk: { @@ -62,6 +60,9 @@ export default { }, changedLength() { return Object.keys(this.changed).length; + }, + noImageSrc() { + return FHC_JS_DATA_STORAGE_OBJECT.app_root + 'skin/images/profilbild_dummy.jpg'; } }, watch: { @@ -69,6 +70,7 @@ export default { this.updateStudent(n); }, data: { + // TODO(chris): use @input instead? handler(n) { let res = {}; for (var k in this.original) { @@ -82,7 +84,6 @@ export default { } } this.changed = res; - this.resetErrors(); }, deep: true } @@ -98,213 +99,264 @@ export default { this.data.familienstand = ''; this.original = {...this.data}; }) - .catch(err => { - console.error(err.response.data || err.message); - }); + .catch(this.$fhcAlert.handleSystemError); }, save() { - CoreRESTClient - .post('components/stv/Student/save/' + this.modelValue.prestudent_id, this.changed) - .then(result => result.data) + this.$refs.form + .send(CoreRESTClient.post('components/stv/Student/save/' + this.modelValue.prestudent_id, this.changed)) .then(result => { - this.resetErrors(); - if (CoreRESTClient.isError(result)) { - let errors = CoreRESTClient.getError(result); - - if (errors === "Generic error") - console.error(errors, result); - else { - for (var k in errors) - this.addError(k, errors[k]); - } - } else { - for (var node of document.querySelectorAll(Object.keys(this.changed).map(el => '#stv-details-' + el).join(','))) - node.classList.add('is-valid'); - if (this.changed.gebdatum !== undefined) - this.gebDatumIsValid = true; - - // TODO(chris): phrase - this.$fhcAlert.alertSuccess('Gespeichert'); - //this.addToast('Gespeichert', '', 'success'); - - this.original = {...this.data}; - this.changed = {}; - } + this.original = {...this.data}; + this.changed = {}; }) - .catch(this.$fhcAlert.handleSystemError/*err => { - // TODO(chris): phrase - this.addToast('Error', err?.response?.data || err?.message, 'error'); - }*/); - }, - resetErrors() { - Array.from(this.$refs.form.getElementsByClassName('is-valid')).forEach(el => el.classList.remove('is-valid')); - Array.from(this.$refs.form.getElementsByClassName('is-invalid')).forEach(el => el.classList.remove('is-invalid')); - Array.from(this.$refs.form.getElementsByClassName('invalid-feedback')).forEach(el => el.remove()); - this.gebDatumIsValid = false; - this.gebDatumIsInvalid = false; - }, - addError(field, msg) { - let id = 'stv-details-' + field; - - let input = document.getElementById(id); - if (field === 'gebdatum') { - this.gebDatumIsInvalid = true; - input = document.getElementById('dp-input-' + id).parentNode; - } - - input.classList.add('is-invalid'); - - let feedback = document.createElement('div'); - feedback.classList.add('invalid-feedback'); - feedback.innerHTML = msg; - input.after(feedback); - /*}, - addToast(header, msg, severity) { - this.$refs.responseToast.add({ - severity: severity, - summary: header, - detail: msg, - life: 3000 - })*/ + .catch(this.$fhcAlert.handleSystemError); } }, created() { this.updateStudent(this.modelValue); }, + //TODO(chris): Phrasen //TODO(chris): Geburtszeit? Anzahl der Kinder? template: ` -
-
+ +
Person
@@ -315,47 +367,79 @@ export default { StudentIn
Loading...
- - ` +
` }; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js b/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js index 95875f868..0f5bcc62e 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js @@ -2,6 +2,8 @@ import {CoreFilterCmpt} from "../../../../filter/Filter.js"; import {CoreRESTClient} from '../../../../../RESTClient.js'; import ZeugnisActions from './Zeugnis/Actions.js'; +const LOCAL_STORAGE_ID = 'stv_details_noten_zeugnis_2024-01-11_stdsem_all'; + export default { components: { CoreFilterCmpt, @@ -13,12 +15,13 @@ export default { data() { return { validStudent: true, - tabulatorEvents: [] + tabulatorEvents: [], + stdsem: '' }; }, computed: { ajaxURL() { - return CoreRESTClient._generateRouterURI('components/stv/Noten/getZeugnis/' + this.student.prestudent_id); + return CoreRESTClient._generateRouterURI('components/stv/Noten/getZeugnis/' + this.student.prestudent_id + this.stdsem); }, tabulatorOptions() { return { @@ -59,29 +62,50 @@ export default { }; } }, + watch: { + ajaxURL(n) { + if (this.$refs.table) + this.$refs.table.tabulator.setData(n); + } + }, methods: { setGrades(selected) { CoreRESTClient .post('components/stv/Noten/update', selected) .then(this.$refs.table.reloadTable) .catch(this.$fhcAlert.handleFormValidation); + }, + saveStdsem(event) { + window.localStorage.setItem(LOCAL_STORAGE_ID, event.target.value ? 'true' : ''); } }, + created() { + const savedPath = window.localStorage.getItem(LOCAL_STORAGE_ID); + this.stdsem = savedPath ? '/all' : ''; + }, + // TODO(chris): phrasen template: `
Kein Student
- - - +
` }; \ No newline at end of file diff --git a/public/js/components/Tabs.js b/public/js/components/Tabs.js index 7d2cf0500..1e77fa996 100644 --- a/public/js/components/Tabs.js +++ b/public/js/components/Tabs.js @@ -11,9 +11,14 @@ export default { 'changed' ], props: { - configUrl: String, + // TODO(chris): rename to config? + configUrl: { + type: [String, Object], + required: true + }, default: String, - modelValue: [String, Number, Boolean, Array, Object, Date, Function, Symbol] + modelValue: [String, Number, Boolean, Array, Object, Date, Function, Symbol], + vertical: Boolean }, data() { return { @@ -37,60 +42,70 @@ export default { } } }, + watch: { + configUrl(n) { + this.initConfig(n); + } + }, methods: { change(key) { this.$emit("change", key) this.current = key; this.$nextTick(() => this.$emit("changed", key)); - } - }, - created() { - CoreRESTClient - .get(this.configUrl) - .then(result => CoreRESTClient.getData(result.data)) - .then(result => { - if (!result) - return; + }, + initConfig(config) { + if (!config) + return; + if (typeof config === 'string' || config instanceof String) + return CoreRESTClient.get(config) + .then(result => CoreRESTClient.getData(result.data)) + .then(this.initConfig) + .catch(this.$fhcAlert.handleSystemError); - const tabs = {}; + console.log(config); + const tabs = {}; - if (Array.isArray(result)) { - result.forEach((config, key) => { - if (!config.component) - return console.error('Component missing for ' + key); + if (Array.isArray(config)) { + config.forEach((item, key) => { + if (!item.component) + return console.error('Component missing for ' + key); - tabs[key] = { - component: Vue.markRaw(Vue.defineAsyncComponent(() => import(config.component))), - title: config.title || key, - config: config.config, - key - } - }); + tabs[key] = { + component: Vue.markRaw(Vue.defineAsyncComponent(() => import(item.component))), + title: item.title || key, + config: item.config, + key + } + }); + } else { + Object.entries(config).forEach(([key, item]) => { + if (!item.component) + return console.error('Component missing for ' + key); - } else { - Object.entries(result).forEach(([key, config]) => { - if (!config.component) - return console.error('Component missing for ' + key); + tabs[key] = { + component: Vue.markRaw(Vue.defineAsyncComponent(() => import(item.component))), + title: item.title || key, + config: item.config, + key + } + }); + } - tabs[key] = { - component: Vue.markRaw(Vue.defineAsyncComponent(() => import(config.component))), - title: config.title || key, - config: config.config, - key - } - }); - } + if (this.current === null || !tabs[this.current]) { if (tabs[this.default]) this.current = this.default; else this.current = Object.keys(tabs)[0]; - this.tabs = tabs; - }) - .catch(this.$fhcAlert.handleSystemError); + } + this.tabs = tabs; + } + }, + created() { + this.initConfig(this.configUrl); }, template: ` -
-