diff --git a/application/controllers/api/frontend/v1/education/Ferien.php b/application/controllers/api/frontend/v1/education/Ferien.php new file mode 100644 index 000000000..419164fa8 --- /dev/null +++ b/application/controllers/api/frontend/v1/education/Ferien.php @@ -0,0 +1,192 @@ +. + */ + +if (!defined('BASEPATH')) exit('No direct script access allowed'); + +//use CI3_Events as Events; + +/** + * This controller operates between (interface) the JS (GUI) and the back-end + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Ferien extends FHCAPI_Controller +{ + /** + * Calls the parent's constructor and prepares libraries and phrases + */ + public function __construct() + { + parent::__construct([ + 'getFerien' => 'basis/ferien:r', + 'getStg' => 'basis/ferien:r', + 'insert' => 'basis/ferien:w', + 'delete' => 'basis/ferien:w' + ]); + + // Load models + $this->load->model('organisation/Ferien_model', 'FerienModel'); + + // Load language phrases + $this->loadPhrases([ + 'ui' + ]); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Get Ferien + * + * @return void + */ + public function getFerien() + { + $studiengang_kz = $this->input->get('studiengang_kz'); + + $this->addMeta('stgkz', $studiengang_kz); + + if (!isset($studiengang_kz)) $this->terminateWithSuccess([]); + + //~ if (isset($studiengang_kz) && !is_numeric($studiengang_kz)) + //~ $this->terminateWithError($this->p->t('ui', 'errorMissingOrInvalidParameters', ['parameter'=> 'Studiengang']), self::ERROR_TYPE_GENERAL); + + $this->FerienModel->addSelect('tbl_ferien.*, , UPPER(typ::varchar(1) || kurzbz) AS studiengang_kuerzel'); + $this->FerienModel->addJoin('public.tbl_studiengang', 'studiengang_kz'); + + if (isset($studiengang_kz) && is_numeric($studiengang_kz)) + $this->FerienModel->db->where('studiengang_kz', $studiengang_kz); + + $this->FerienModel->addOrder('vondatum', 'DESC'); + $result = $this->FerienModel->load(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * Get list of Studiengaenge + * + * @return void + */ + public function getStg() + { + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + + $this->StudiengangModel->addSelect(' tbl_studiengang.*, UPPER(typ::varchar(1) || kurzbz) AS kuerzel'); + $this->StudiengangModel->addOrder('typ, kurzbz'); + $result = $this->StudiengangModel->load(); + + $data = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($data); + } + + /** + * Save Ferien + * + * @return void + */ + public function insert() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('vondatum', 'Von Datum', 'required|is_valid_date'); + $this->form_validation->set_rules('bisdatum', 'Bis Datum', 'required|is_valid_date'); + $this->form_validation->set_rules('bezeichnung', 'Bezeichnung', 'required|max_length[128]'); + $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required|numeric'); + + //Events::trigger('konto_insert_validation', $this->form_validation); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $allowed = [ + 'vondatum', + 'bisdatum', + 'bezeichnung', + 'studiengang_kz' + ]; + + $data = []; + + // TODO add insertaum and updateamum? + //~ $data = [ + //~ 'insertamum' => date('c'), + //~ 'insertvon' => getAuthUID() + //~ ]; + foreach ($allowed as $field) + { + if ($this->input->post($field) !== null) $data[$field] = $this->input->post($field); + } + + $result = []; + + $id = $this->getDataOrTerminateWithError($this->FerienModel->insert($data)); + + $this->terminateWithSuccess(hasData($id) ? getData($id) : null); + } + + /** + * Delete Ferien + * + * @return void + */ + public function delete() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('ferien_id', 'Ferien Id', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $ferien_id = $this->input->post('ferien_id'); + + $this->FerienModel->addSelect('ferien_id'); + $result = $this->FerienModel->load($ferien_id); + $this->addMeta('res', $result); + + if (!hasData($result)) + $this->terminateWithError($this->p->t('ferien', 'error_missing', [ + 'ferien_id' => $ferien_id + ])); + + //~ $_POST['studiengang_kz'] = current($result)->studiengang_kz; + + //~ $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'has_permissions_for_stg[admin:rw,assistenz:rw]'); + + //~ Events::trigger('konto_delete_validation', $this->form_validation); + + //~ if (!$this->form_validation->run()) + //~ $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + //Events::trigger('konto_delete', $ferien_id); + + $result = $this->getDataOrTerminateWithError($this->FerienModel->delete($ferien_id)); + //~ if (isError($result)) { + //~ if (getCode($result) != 42) + //~ $this->terminateWithError(getError($result)); + //~ $this->terminateWithError($this->p->t('konto', 'error_delete_level')); + //~ } + + $this->terminateWithSuccess(); + } +} diff --git a/application/controllers/lehre/Ferienverwaltung.php b/application/controllers/lehre/Ferienverwaltung.php new file mode 100644 index 000000000..6d531579a --- /dev/null +++ b/application/controllers/lehre/Ferienverwaltung.php @@ -0,0 +1,44 @@ + ['admin:r', 'assistenz:r'] + ) + ); + + // Loads WidgetLib + //$this->load->library('WidgetLib'); + + // Loads phrases system + $this->loadPhrases( + array( + 'global', + 'ui' + //'ferien' + ) + ); + } + + // ----------------------------------------------------------------------------------------------------------------- + // Public methods + + /** + * Everything has a beginning + */ + public function index() + { + $this->load->view('lehre/ferienverwaltung.php'); + } +} diff --git a/application/models/organisation/Ferien_model.php b/application/models/organisation/Ferien_model.php index 2ade75aa4..d1af53f21 100644 --- a/application/models/organisation/Ferien_model.php +++ b/application/models/organisation/Ferien_model.php @@ -9,6 +9,6 @@ class Ferien_model extends DB_Model { parent::__construct(); $this->dbTable = 'lehre.tbl_ferien'; - $this->pk = array('studiengang_kz', 'bezeichnung'); + $this->pk = 'ferien_id'; } } diff --git a/application/views/lehre/ferienverwaltung.php b/application/views/lehre/ferienverwaltung.php new file mode 100644 index 000000000..3a9a615ca --- /dev/null +++ b/application/views/lehre/ferienverwaltung.php @@ -0,0 +1,29 @@ + 'Ferienverwaltung', + 'axios027' => true, + 'bootstrap5' => true, + 'fontawesome6' => true, + 'vue3' => true, + 'filtercomponent' => true, + 'navigationcomponent' => true, + 'tabulator6' => true, + 'primevue3' => true, + 'vuedatepicker11' => true, + 'customJSModules' => array('public/js/apps/lehre/Ferienverwaltung/Ferienverwaltung.js'), + ); + + $this->load->view('templates/FHC-Header', $includesArray); +?> + +
+ +
+
+ +
+
+
+ +load->view('templates/FHC-Footer', $includesArray); ?> + diff --git a/public/js/api/factory/ferienverwaltung/ferienverwaltung.js b/public/js/api/factory/ferienverwaltung/ferienverwaltung.js new file mode 100644 index 000000000..093e62255 --- /dev/null +++ b/public/js/api/factory/ferienverwaltung/ferienverwaltung.js @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2025 fhcomplete.org + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +export default { + getFerien(studiengang_kz) { + return { + method: 'get', + url: 'api/frontend/v1/education/ferien/getFerien', + params: { + studiengang_kz + } + }; + }, + getStg() { + return { + method: 'get', + url: 'api/frontend/v1/education/ferien/getStg' + }; + }, + insert(params) { + return { + method: 'post', + url: 'api/frontend/v1/education/ferien/insert', + params + }; + }, + delete(ferien_id) { + return { + method: 'post', + url: 'api/frontend/v1/education/ferien/delete', + params: { ferien_id } + }; + } +}; \ No newline at end of file diff --git a/public/js/apps/lehre/Ferienverwaltung/Ferienverwaltung.js b/public/js/apps/lehre/Ferienverwaltung/Ferienverwaltung.js new file mode 100644 index 000000000..ad7106366 --- /dev/null +++ b/public/js/apps/lehre/Ferienverwaltung/Ferienverwaltung.js @@ -0,0 +1,12 @@ +import Ferienverwaltung from '../../../components/Ferienverwaltung/Ferienverwaltung.js'; +import PluginsPhrasen from '../../../plugins/Phrasen.js'; + +const app = Vue.createApp({ + name: 'FerienverwaltungApp', + components: { + Ferienverwaltung + } +}); +app + .use(PluginsPhrasen) + .mount('#main'); \ No newline at end of file diff --git a/public/js/components/Ferienverwaltung/Ferienverwaltung.js b/public/js/components/Ferienverwaltung/Ferienverwaltung.js new file mode 100644 index 000000000..d1f6bc5b6 --- /dev/null +++ b/public/js/components/Ferienverwaltung/Ferienverwaltung.js @@ -0,0 +1,213 @@ +import {CoreFilterCmpt} from "../filter/Filter.js"; +import FormInput from "../Form/Input.js"; +import FerienNew from "./New.js"; +//import KontoEdit from "./Konto/Edit.js"; + +import ApiFerienverwaltung from '../../api/factory/ferienverwaltung/ferienverwaltung.js'; + +export default { + name: "Ferienverwaltung", + components: { + CoreFilterCmpt, + FormInput, + FerienNew + //KontoEdit + }, + props: { + //modelValue: Object, + //~ config: { + //~ type: Object, + //~ default: {} + //~ } + }, + data() { + return { + studiengang_kz_list: [], + studiengang_kz: null, + loading: false, + tabulatorOptions: { + ajaxURL: 'dummy', + ajaxRequestFunc: () => this.$api.call( + ApiFerienverwaltung.getFerien(this.studiengang_kz) + ), + ajaxResponse: (url, params, response) => response.data, + columns: [ + {title:"Ferien Id", field:"ferien_id", visible: false}, + {title:"Studiengang", field:"studiengang_kuerzel"}, + { + title:"Datum von", + field:"vondatum", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + } + }, + { + title:"Datum bis", + field:"bisdatum", + formatter: function (cell) { + const dateStr = cell.getValue(); + if (!dateStr) return ""; + + const date = new Date(dateStr); + return date.toLocaleString("de-DE", { + day: "2-digit", + month: "2-digit", + year: "numeric", + hour12: false + }); + } + }, + {title:"Bezeichnung", field:"bezeichnung"}, + {title:"Aktionen", field: "actions", + minWidth: 150, // Ensures Action-buttons will be always fully displayed + formatter: (cell, formatterParams, onRendered) => { + let container = document.createElement('div'); + container.className = "d-flex gap-2"; + + //~ let button = document.createElement('button'); + //~ button.className = 'btn btn-outline-secondary btn-action'; + //~ button.innerHTML = ''; + //~ button.title = this.$p.t('person', 'adresse_edit'); + //~ button.addEventListener('click', (event) => + //~ this.actionEditAdress(cell.getData().adresse_id) + //~ ); + //~ container.append(button); + let button = document.createElement('button'); + button.className = 'btn btn-outline-secondary'; + button.innerHTML = ''; + button.addEventListener('click', evt => { + evt.stopPropagation(); + this.$fhcAlert + .confirmDelete() + .then(result => result ? cell.getData().ferien_id : Promise.reject({handled:true})) + .then(ferien_id => this.$api.call(ApiFerienverwaltung.delete(ferien_id))) + .then(() => { + //cell.getRow().delete(); + this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete')); + this.reload(); + }) + .catch(this.$fhcAlert.handleSystemError); + }); + container.append(button); + + return container; + }, + frozen: true + } + ] + }, + tabulatorEvents: [ + { + event: 'tableBuilt', + handler: async () => { + + //await this.$p.loadCategory(['ferien', 'ui']); + await this.$p.loadCategory(['global', 'ferien']); + + let cm = this.$refs.table.tabulator.columnManager; + + cm.getColumnByField('ferien_id').component.updateDefinition({ + title: this.$p.t('ferien', 'ferien_id'), + }); + cm.getColumnByField('studiengang_kuerzel').component.updateDefinition({ + title: this.$p.t('ferien', 'studiengang_kuerzel'), + }); + cm.getColumnByField('vondatum').component.updateDefinition({ + title: this.$p.t('ferien', 'vondatum'), + }); + cm.getColumnByField('bisdatum').component.updateDefinition({ + title: this.$p.t('ferien', 'bisdatum'), + }); + cm.getColumnByField('bezeichnung').component.updateDefinition({ + title: this.$p.t('global', 'bezeichnung'), + }); + cm.getColumnByField('actions').component.updateDefinition({ + title: this.$p.t('global', 'aktionen') + }); + } + } + ] + } + }, + computed: { + }, + methods: { + reload() { + this.$refs.table.reloadTable(); + }, + updateData(data) { + if (!data) + return this.reload(); + //this.$refs.table.tabulator.updateOrAddData(data); + }, + actionNew() { + this.$refs.new.open(); + }, + loadByStg() { + this.reload(); + } + }, + created() { + this.loading = true; + this.$api + .call(ApiFerienverwaltung.getStg()) + .then(result => { + this.studiengang_kz_list = result.data; + this.loading = false; + } + ) + .catch(error => { + if (error) + this.$fhcAlert.handleSystemError(error); + this.loading = false; + }); + }, + template: ` +
+
+
+
+ + +
+
+
+ + + + +
` +}; \ No newline at end of file diff --git a/public/js/components/Ferienverwaltung/New.js b/public/js/components/Ferienverwaltung/New.js new file mode 100644 index 000000000..dad8a4034 --- /dev/null +++ b/public/js/components/Ferienverwaltung/New.js @@ -0,0 +1,120 @@ +import BsModal from "../Bootstrap/Modal.js"; +import BsConfirm from "../Bootstrap/Confirm.js"; +import CoreForm from "../Form/Form.js"; +import FormValidation from "../Form/Validation.js"; +import FormInput from "../Form/Input.js"; + +import ApiFerien from '../../api/factory/ferienverwaltung/ferienverwaltung.js'; + +export default { + components: { + BsModal, + CoreForm, + FormValidation, + FormInput + }, + props: { + studiengang_kz_list: { + type: Array, + required: true + } + }, + data() { + return { + loading: false, + data: {}, + }; + }, + computed: { + }, + methods: { + save() { + this.$refs.form.clearValidation(); + this.loading = true; + + this.$refs.form + .call(ApiFerien.insert(this.data)) + .then(result => { + this.$emit('saved', result.data); + this.loading = false; + this.$refs.modal.hide(); + this.$fhcAlert.alertSuccess(this.$p.t('ui/gespeichert')); + }) + .catch(error => { + if (error) + this.$fhcAlert.handleSystemError(error); + this.loading = false; + }); + }, + open() { + this.data = { + studiengang_kz: null, + bezeichnung: '', + vondatum: null, + bisdatum: null + }; + this.$refs.modal.show(); + }, + preventCloseOnLoading(ev) { + if (this.loading) + ev.returnValue = false; + } + }, + template: ` + + + + +
+ + + + + + + + + + + + +
+ + +
+
` +}; \ No newline at end of file