From f0d0c0837a2de5e916149b61d86dd3282075553e Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Sat, 17 Jun 2023 20:51:33 +0200 Subject: [PATCH 01/74] added Filter for Software Management --- system/filtersupdate.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/system/filtersupdate.php b/system/filtersupdate.php index 241e44f2f..8652f4316 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -1256,6 +1256,30 @@ $filters = array( } ', 'oe_kurzbz' => null, + ), + array( + 'app' => 'core', + 'dataset_name' => 'softwareManagement', + 'filter_kurzbz' => 'SoftwareManagement', + 'description' => '{Software Verwaltung}', + 'sort' => 1, + 'default_filter' => true, + 'filter' => ' + { + "name": "SoftwareManagement", + "columns": [ + {"name": "Software Kurzbezeichnung"}, + {"name": "Version"}, + {"name": "Beschreibung"}, + {"name": "Hersteller"}, + {"name": "Betriebssystem"}, + {"name": "Aktiv"}, + {"name": "Softwarestatus Kurzbezeichnung"} + ], + "filters": [] + } + ', + 'oe_kurzbz' => null, ) ); From 7356b17688cf0356bcc8012aaa8aebde87068aab Mon Sep 17 00:00:00 2001 From: Cris Date: Mon, 3 Jul 2023 09:37:32 +0200 Subject: [PATCH 02/74] Added SW-ID column to SW-Table --- system/filtersupdate.php | 1 + 1 file changed, 1 insertion(+) diff --git a/system/filtersupdate.php b/system/filtersupdate.php index 8652f4316..d226e9996 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -1268,6 +1268,7 @@ $filters = array( { "name": "SoftwareManagement", "columns": [ + {"name": "ID"}, {"name": "Software Kurzbezeichnung"}, {"name": "Version"}, {"name": "Beschreibung"}, From 71e86cfcdeb93ce26184e58f5065837a2d964d60 Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Mon, 3 Jul 2023 11:45:15 +0200 Subject: [PATCH 03/74] filter.js bugfixes: saving customfilter, and set columns before data (necessary e.g. for nested tabulator) --- public/js/components/filter/Filter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/js/components/filter/Filter.js b/public/js/components/filter/Filter.js index 2bf878e5a..3b5760f93 100644 --- a/public/js/components/filter/Filter.js +++ b/public/js/components/filter/Filter.js @@ -194,8 +194,8 @@ export const CoreFilterCmpt = { } }, _updateTabulator() { - this.tabulator.setData(this.filteredData); this.tabulator.setColumns(this.filteredColumns); + this.tabulator.setData(this.filteredData); }, /** * @@ -371,7 +371,7 @@ export const CoreFilterCmpt = { this.startFetchCmpt( CoreFilterAPIs.saveCustomFilter, { - customFilterName: this.$refscustomFilterName.value + customFilterName: this.$refs.customFilterName.value }, this.getFilter ); From fc147f577ab8fe529bad4ced7bd9d8f022bf649e Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Tue, 4 Jul 2023 12:17:15 +0200 Subject: [PATCH 04/74] filter.js: fix for nested tabulator: set columns before set data, filtersupdate: renamed columns --- public/js/components/filter/Filter.js | 2 +- system/filtersupdate.php | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/public/js/components/filter/Filter.js b/public/js/components/filter/Filter.js index 776405614..9c53afdef 100644 --- a/public/js/components/filter/Filter.js +++ b/public/js/components/filter/Filter.js @@ -226,9 +226,9 @@ export const CoreFilterCmpt = { } }, _updateTabulator() { + this.tabulator.setColumns(this.filteredColumns); this.tabulator.setData(this.filteredData); this.tabulatorHasSelector = this.filteredColumns.filter(el => el.formatter == 'rowSelection').length; - this.tabulator.setColumns(this.filteredColumns); }, /** * diff --git a/system/filtersupdate.php b/system/filtersupdate.php index 8652f4316..1c303ad43 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -1268,13 +1268,12 @@ $filters = array( { "name": "SoftwareManagement", "columns": [ - {"name": "Software Kurzbezeichnung"}, - {"name": "Version"}, - {"name": "Beschreibung"}, - {"name": "Hersteller"}, - {"name": "Betriebssystem"}, - {"name": "Aktiv"}, - {"name": "Softwarestatus Kurzbezeichnung"} + {"name": "software_kurzbz"}, + {"name": "version"}, + {"name": "beschreibung"}, + {"name": "hersteller"}, + {"name": "os"}, + {"name": "aktiv"} ], "filters": [] } From 539efcb6ecfeb0d9e54d9a4d07949964b268bb87 Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Thu, 6 Jul 2023 12:03:38 +0200 Subject: [PATCH 05/74] added Modal.js to Bootstrap components --- public/js/components/Bootstrap/Modal.js | 109 ++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 public/js/components/Bootstrap/Modal.js diff --git a/public/js/components/Bootstrap/Modal.js b/public/js/components/Bootstrap/Modal.js new file mode 100644 index 000000000..90cec2d50 --- /dev/null +++ b/public/js/components/Bootstrap/Modal.js @@ -0,0 +1,109 @@ +export default { + data: () => ({ + modal: null + }), + props: { + backdrop: { + type: [Boolean,String], + default: true, + validator(value) { + return ['static', true, false].includes(value); + } + }, + focus: { + type: Boolean, + default: true + }, + keyboard: { + type: Boolean, + default: true + }, + noCloseBtn: Boolean, + dialogClass: [String,Array,Object] + }, + emits: [ + "hideBsModal", + "hiddenBsModal", + "hidePreventedBsModal", + "showBsModal", + "shownBsModal" + ], + methods: { + dispose() { + return this.modal.dispose(); + }, + handleUpdate() { + return this.modal.handleUpdate(); + }, + hide() { + return this.modal.hide(); + }, + show(relatedTarget) { + return this.modal.show(relatedTarget); + }, + toggle() { + return this.modal.toggle(); + } + }, + mounted() { + if(this.$refs.modal) + { + this.modal = new bootstrap.Modal(this.$refs.modal, { + backdrop: this.backdrop, + focus: this.focus, + keyboard: this.keyboard + }); + } + }, + popup(body, options, title, footer) { + const BsModal = this, + slots = {}; + if (body !== undefined) + slots.default = () => body; + if (title !== undefined) + slots.title = () => title; + if (footer !== undefined) + slots.footer = () => footer; + return new Promise((resolve,reject) => { + const instance = Vue.createApp({ + setup() { + return () => Vue.h(BsModal, {...{ + class: 'fade' + },...options, ...{ + ref: 'modal', + 'onHidden.bs.modal': instance.unmount + }}, slots); + }, + mounted() { + this.$refs.modal.show(); + }, + beforeUnmount() { + if (this.$refs.modal) + this.$refs.modal.result !== false ? resolve(this.$refs.modal.result) : reject(); + }, + unmounted() { + wrapper.parentElement.removeChild(wrapper); + } + }); + const wrapper = document.createElement("div"); + instance.mount(wrapper); + document.body.appendChild(wrapper); + }); + }, + template: `` +} From d88ff104a318950ca55cccb2a7f22cd6f2ab1804 Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Tue, 18 Jul 2023 19:11:10 +0200 Subject: [PATCH 06/74] filter component: added property tabulatorAdditionalColumns for displaying additional columns not in filter --- public/js/components/filter/Filter.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/js/components/filter/Filter.js b/public/js/components/filter/Filter.js index fbd9ee268..2a0791537 100644 --- a/public/js/components/filter/Filter.js +++ b/public/js/components/filter/Filter.js @@ -55,6 +55,7 @@ export const CoreFilterCmpt = { }, tabulatorOptions: Object, tabulatorEvents: Array, + tabulatorAdditionalColumns: Array, tableOnly: Boolean, reload: Boolean, download: { @@ -137,7 +138,10 @@ export const CoreFilterCmpt = { { // If the column has to be displayed or not col.visible = selectedFields.indexOf(col.field) >= 0; - if (col.formatter == 'rowSelection') + if ( + col.formatter == 'rowSelection' + || (this.tabulatorAdditionalColumns && this.tabulatorAdditionalColumns.indexOf(col.title) >= 0) + ) col.visible = true; if (col.hasOwnProperty('resizable')) From 44182af5fa2cbb4641a7d33fff48f0e51faa01d0 Mon Sep 17 00:00:00 2001 From: Cris Date: Mon, 31 Jul 2023 09:30:45 +0200 Subject: [PATCH 07/74] Formatted Tabulator Header: Abstaende vergroessert Abstand Titel zu Actionbuttons und zwischen Actionbuttons untereinander vergroessert --- public/js/components/filter/Filter.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/js/components/filter/Filter.js b/public/js/components/filter/Filter.js index 2a0791537..240410677 100644 --- a/public/js/components/filter/Filter.js +++ b/public/js/components/filter/Filter.js @@ -507,7 +507,7 @@ export const CoreFilterCmpt = {
-
@@ -516,7 +516,7 @@ export const CoreFilterCmpt = {
-
+
- Mit {{selectedData.length}} ausgewählten: + Mit {{selectedData.length}} ausgewählten:
From b70011436e57ee5236bd25c941fb99b547501dec Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 2 Aug 2023 13:39:47 +0200 Subject: [PATCH 08/74] Added column 'softwarestatus_kurzbz' to filtersupdate --- system/filtersupdate.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/filtersupdate.php b/system/filtersupdate.php index 1c303ad43..872e2b95b 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -1273,7 +1273,8 @@ $filters = array( {"name": "beschreibung"}, {"name": "hersteller"}, {"name": "os"}, - {"name": "aktiv"} + {"name": "aktiv"}, + {"name": "softwarestatus_kurzbz"} ], "filters": [] } From 553f2feaa4495ae9be80dd967fd47403db3b6048 Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Wed, 2 Aug 2023 16:22:10 +0200 Subject: [PATCH 09/74] filter component: enabled nested tabulator --- public/js/components/filter/Filter.js | 66 ++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/public/js/components/filter/Filter.js b/public/js/components/filter/Filter.js index 240410677..93bb69274 100644 --- a/public/js/components/filter/Filter.js +++ b/public/js/components/filter/Filter.js @@ -65,7 +65,9 @@ export const CoreFilterCmpt = { newBtnShow: Boolean, newBtnClass: [String, Array, Object], newBtnDisabled: Boolean, - newBtnLabel: String + newBtnLabel: String, + idField: String, + parentIdField: String }, data: function() { return { @@ -198,6 +200,13 @@ export const CoreFilterCmpt = { if (tabulatorOptions.columns && tabulatorOptions.columns.filter(el => el.formatter == 'rowSelection').length) this.tabulatorHasSelector = true; + if (this.idField) { + // enable nested tabulator if parent Id given + if (this.parentIdField) tabulatorOptions.dataTree = true; + // set tabulator index + tabulatorOptions.index = this.idField; + } + // Start the tabulator with the build options this.tabulator = new Tabulator( this.$refs.table, @@ -214,6 +223,32 @@ export const CoreFilterCmpt = { this.tabulator.on("rowSelectionChanged", data => { this.selectedData = data; }); + // if nested tabulator, restructure data + if (this.parentIdField && this.idField) { + this.tabulator.on("dataLoading", data => { + let toDelete = []; + + // loop through all data + for (let childIdx = 0; childIdx < data.length; childIdx++) + { + let child = data[childIdx]; + + // if it has parent id, it is a child + if (child[this.parentIdField]) + { + // append the child on the right place. If parent found, mark original sw child on 0 level for deleting + if (this.appendChild(data, child)) toDelete.push(childIdx); + } + } + + // delete the marked children from 0 level + for (let counter = 0; counter < toDelete.length; counter++) + { + // decrease index by counter as index of data array changes after every deletion + data.splice(toDelete[counter] - counter, 1); + } + }); + } if (this.tableOnly) { this.tabulator.on('tableBuilt', () => { const cols = this.tabulator.getColumns(); @@ -479,6 +514,35 @@ export const CoreFilterCmpt = { }, this.getFilter ); + }, + // append child to it's parent + appendChild(data, child) { + // get parent id + let parentId = child[this.parentIdField]; + + // loop thorugh all data + for (let parentIdx = 0; parentIdx < data.length; parentIdx++) + { + let parent = data[parentIdx]; + + // if it's the parent + if (parent[this.idField] == parentId) + { + // create children array if not done yet + if (!parent._children) parent._children = []; + + // append the child + parent._children.push(child); + + // parent found + return true; + } + // search children for parents + else if (parent._children) this.appendChild(parent._children, child); + } + + // parent not found + return false; } }, beforeCreate() { From 2f001987f34379aac2605c8803c91b3a47b88424 Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Wed, 2 Aug 2023 19:14:58 +0200 Subject: [PATCH 10/74] Filter.js additional columns: additional columns are displayed based on field name, not title --- public/js/components/filter/Filter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/components/filter/Filter.js b/public/js/components/filter/Filter.js index 93bb69274..4c54c94fc 100644 --- a/public/js/components/filter/Filter.js +++ b/public/js/components/filter/Filter.js @@ -142,7 +142,7 @@ export const CoreFilterCmpt = { col.visible = selectedFields.indexOf(col.field) >= 0; if ( col.formatter == 'rowSelection' - || (this.tabulatorAdditionalColumns && this.tabulatorAdditionalColumns.indexOf(col.title) >= 0) + || (this.tabulatorAdditionalColumns && this.tabulatorAdditionalColumns.indexOf(col.field) >= 0) ) col.visible = true; From 4e17be39f65bc5e4e043c2b15a7674520d0eb727 Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 3 Aug 2023 09:44:28 +0200 Subject: [PATCH 11/74] Added column 'actions' to filtersupdate --- system/filtersupdate.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/filtersupdate.php b/system/filtersupdate.php index 872e2b95b..741f09ef6 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -1274,7 +1274,8 @@ $filters = array( {"name": "hersteller"}, {"name": "os"}, {"name": "aktiv"}, - {"name": "softwarestatus_kurzbz"} + {"name": "softwarestatus_kurzbz"}, + {"name": "actions"} ], "filters": [] } From 56230e3752ad01c52b7c33d7a1f971f9b52498a6 Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 3 Aug 2023 09:45:45 +0200 Subject: [PATCH 12/74] Changed button-color of Tabulators Header-'ADD Button' to primary color --- public/js/components/filter/Filter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/components/filter/Filter.js b/public/js/components/filter/Filter.js index 240410677..72eae8123 100644 --- a/public/js/components/filter/Filter.js +++ b/public/js/components/filter/Filter.js @@ -517,7 +517,7 @@ export const CoreFilterCmpt = {
- From 4a2cdaf52ae7d3d6eb5a53c314de9fa2f6202e05 Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Fri, 4 Aug 2023 14:46:53 +0200 Subject: [PATCH 13/74] added primevue autocomplete --- application/views/templates/FHC-Footer.php | 3 ++- composer.json | 2 +- public/js/components/filter/API.js | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/application/views/templates/FHC-Footer.php b/application/views/templates/FHC-Footer.php index c461dd8b0..f360861e5 100644 --- a/application/views/templates/FHC-Footer.php +++ b/application/views/templates/FHC-Footer.php @@ -107,7 +107,7 @@ if ($tinymce5 === true) generateJSsInclude('vendor/tinymce/tinymce5/tinymce.min.js'); // Vue 3 JS - if ($vue3 === true) + if ($vue3 === true) { generateJSsInclude('vendor/vuejs/vuejs3/vue.global.prod.js'); generateJSsInclude('vendor/vuejs/vuerouter4/vue-router.global.js'); @@ -122,6 +122,7 @@ generateJSsInclude('vendor/npm-asset/primevue/column/column.min.js'); generateJSsInclude('vendor/npm-asset/primevue/calendar/calendar.min.js'); generateJSsInclude('vendor/npm-asset/primevue/skeleton/skeleton.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/autocomplete/autocomplete.min.js'); } // -------------------------------------------------------------------------------------------------------- diff --git a/composer.json b/composer.json index 825ed5625..840a53124 100644 --- a/composer.json +++ b/composer.json @@ -400,7 +400,7 @@ "nategood/httpful": "0.2.*", "netcarver/textile": "3.7.*", "nicolaskruchten/pivottable": "2.23.0", - "npm-asset/primevue": "3.15.*", + "npm-asset/primevue": "3.29.*", "npm-asset/primeicons": "5.0.0", "olifolkerd/tabulator4": "4.9.*", diff --git a/public/js/components/filter/API.js b/public/js/components/filter/API.js index ff09c452d..cc3f229b4 100644 --- a/public/js/components/filter/API.js +++ b/public/js/components/filter/API.js @@ -17,7 +17,7 @@ import {CoreRESTClient} from '../../RESTClient.js'; -// +// const CORE_FILTER_CMPT_TIMEOUT = 7000; /** From b7a3d2dcb4cc89c7f6e37d3cc1367267ddcc9b07 Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 9 Aug 2023 10:57:06 +0200 Subject: [PATCH 14/74] Removed column 'actions' from filtersupdate --- system/filtersupdate.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/system/filtersupdate.php b/system/filtersupdate.php index 741f09ef6..872e2b95b 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -1274,8 +1274,7 @@ $filters = array( {"name": "hersteller"}, {"name": "os"}, {"name": "aktiv"}, - {"name": "softwarestatus_kurzbz"}, - {"name": "actions"} + {"name": "softwarestatus_kurzbz"} ], "filters": [] } From e1c23fc6fa80032da7b5455e837bb030634a9871 Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 10 Aug 2023 11:34:54 +0200 Subject: [PATCH 15/74] Added Filter ImageVerwaltung --- system/filtersupdate.php | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/system/filtersupdate.php b/system/filtersupdate.php index 872e2b95b..0fe7e11c5 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -1280,6 +1280,30 @@ $filters = array( } ', 'oe_kurzbz' => null, + ), + array( + 'app' => 'core', + 'dataset_name' => 'imageVerwaltung', + 'filter_kurzbz' => 'ImageVerwaltung', + 'description' => '{Image Verwaltung}', + 'sort' => 1, + 'default_filter' => true, + 'filter' => ' + { + "name": "ImageVerwaltung", + "columns": [ + {"name": "bezeichnung"}, + {"name": "betriebssystem"}, + {"name": "verfuegbarkeit_start"}, + {"name": "verfuegbarkeit_ende"}, + {"name": "anmerkung"}, + {"name": "ort_count"}, + {"name": "software_count"} + ], + "filters": [] + } + ', + 'oe_kurzbz' => null, ) ); From fa3a718ad4e0e8859e5e453ef327277e2d6b012f Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 21 Sep 2023 14:40:05 +0200 Subject: [PATCH 16/74] Added getAutocompleteSuggestions method to OE Model Get OEs by eventQuery string. Use with autocomplete event queries. --- .../organisation/Organisationseinheit_model.php | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/application/models/organisation/Organisationseinheit_model.php b/application/models/organisation/Organisationseinheit_model.php index bec4aee47..4a64ee055 100644 --- a/application/models/organisation/Organisationseinheit_model.php +++ b/application/models/organisation/Organisationseinheit_model.php @@ -188,4 +188,20 @@ class Organisationseinheit_model extends DB_Model } return $this->loadWhere($condition); } + + /** + * Get OEs by eventQuery string. Use with autocomplete event queries. + * @param $eventQuery String + * @return array + */ + public function getAutocompleteSuggestions($eventQuery) + { + $this->addSelect('oe_kurzbz'); + $this->addSelect('organisationseinheittyp_kurzbz, oe_kurzbz, bezeichnung, aktiv, lehre'); + $this->addOrder('organisationseinheittyp_kurzbz, bezeichnung'); + + return $this->loadWhere(" + oe_kurzbz ILIKE '%". $this->escapeLike($eventQuery). "%' + "); + } } From 4e11e12c9962fad6bf6d7f574f2922ed97e2fcef Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 21 Sep 2023 14:40:50 +0200 Subject: [PATCH 17/74] Removed aktiv column from SoftwareManagement Filter Not used anymore. --- system/filtersupdate.php | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/system/filtersupdate.php b/system/filtersupdate.php index 0fe7e11c5..909dfc601 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -1273,7 +1273,6 @@ $filters = array( {"name": "beschreibung"}, {"name": "hersteller"}, {"name": "os"}, - {"name": "aktiv"}, {"name": "softwarestatus_kurzbz"} ], "filters": [] @@ -1304,6 +1303,30 @@ $filters = array( } ', 'oe_kurzbz' => null, + ), + array( + 'app' => 'core', + 'dataset_name' => 'lizenzserverVerwaltung', + 'filter_kurzbz' => 'LizenzserverVerwaltung', + 'description' => '{Lizenzserver Verwaltung}', + 'sort' => 1, + 'default_filter' => true, + 'filter' => ' + { + "name": "LizenzserverVerwaltung", + "columns": [ + {"name": "lizenzserver_kurzbz"}, + {"name": "bezeichnung"}, + {"name": "macadresse"}, + {"name": "ipadresse"}, + {"name": "ansprechpartner"}, + {"name": "anmerkung"}, + {"name": "location"} + ], + "filters": [] + } + ', + 'oe_kurzbz' => null, ) ); From af678b3c562ee58588b42833ffc2b45c796e0c47 Mon Sep 17 00:00:00 2001 From: KarpAlex Date: Mon, 9 Oct 2023 14:29:38 +0200 Subject: [PATCH 18/74] added vue datepicker to composer --- composer.json | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 840a53124..256aaba74 100644 --- a/composer.json +++ b/composer.json @@ -348,6 +348,28 @@ } } }, + { + "type": "package", + "package": { + "name": "vuejs/vuedatepicker_js", + "version": "5.4.0", + "dist": { + "url": "https://unpkg.com/@vuepic/vue-datepicker@4.2.3/dist/vue-datepicker.iife.js", + "type": "file" + } + } + }, + { + "type": "package", + "package": { + "name": "vuejs/vuedatepicker_css", + "version": "5.4.0", + "dist": { + "url": "https://unpkg.com/@vuepic/vue-datepicker@4.2.3/dist/main.css", + "type": "file" + } + } + }, { "type": "composer", "url": "https://asset-packagist.org" @@ -420,7 +442,9 @@ "twbs/bootstrap5": "5.1.*", "vuejs/vuejs3": "3.2.33", - "vuejs/vuerouter4": "4.1.3" + "vuejs/vuerouter4": "4.1.3", + "vuejs/vuedatepicker_js": "5.4.0", + "vuejs/vuedatepicker_css": "5.4.0" }, "config": { "bin-dir": "vendor/bin" From 0f80b9d31b337766da425b90cc0c3ae20c489972 Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 17 Oct 2023 11:30:35 +0200 Subject: [PATCH 19/74] Added Primevue-Toast and -Confirmdialog libraries to FHC-Footer --- application/views/templates/FHC-Footer.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/application/views/templates/FHC-Footer.php b/application/views/templates/FHC-Footer.php index f360861e5..e7e593d42 100644 --- a/application/views/templates/FHC-Footer.php +++ b/application/views/templates/FHC-Footer.php @@ -123,6 +123,10 @@ generateJSsInclude('vendor/npm-asset/primevue/calendar/calendar.min.js'); generateJSsInclude('vendor/npm-asset/primevue/skeleton/skeleton.min.js'); generateJSsInclude('vendor/npm-asset/primevue/autocomplete/autocomplete.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/toast/toast.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/toastservice/toastservice.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/confirmdialog/confirmdialog.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/confirmationservice/confirmationservice.min.js'); } // -------------------------------------------------------------------------------------------------------- From b01cd99a93715dde6f21ebea666d90fbc3143164 Mon Sep 17 00:00:00 2001 From: cgfhtw Date: Thu, 19 Oct 2023 14:10:55 +0200 Subject: [PATCH 20/74] Plugin: Fhc Alert --- public/js/plugin/FhcAlert.js | 369 +++++++++++++++++++++++++++++++++++ 1 file changed, 369 insertions(+) create mode 100644 public/js/plugin/FhcAlert.js diff --git a/public/js/plugin/FhcAlert.js b/public/js/plugin/FhcAlert.js new file mode 100644 index 000000000..5e1111dd6 --- /dev/null +++ b/public/js/plugin/FhcAlert.js @@ -0,0 +1,369 @@ +/** + * Copyright (C) 2022 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 . + * + * @usage: + * Preperations: + * Be sure to have PrimeVue loaded with the toast and confirmdialog + * components as primevue variable + * Install: + * Import this Plugin and install it with the app.use() function. + * Use: + * In your component you can call now the global property $fhcAlert + * which has the following functions: + * + * alertSuccess + * ------------ + * Displays a success message + * @param string message + * @return void + * + * alertInfo + * --------- + * Displays an info message + * @param string message + * @return void + * + * alertWarning + * ------------ + * Displays a warning + * @param string message + * @return void + * + * alertError + * ---------- + * Displays an error + * @param string message + * @return void + * + * alertSystemError + * ---------------- + * Displays an alert with the error details and a button to mail + * the error to the Support Team + * @param string message + * @return void + * + * confirmDelete + * ------------- + * Displays a confirmation dialog and returns a Promise which resolves + * with true or false depending und the pressed button. + * @return Promise + * + * alertDefault + * ------------ + * Displays an alert + * @param string severity can be 'success', 'info', 'warning', 'error' + * @param string title + * @param string message + * @param boolean sticky (optional) defaults to false + * @return void + * + * alertMultiple + * ------------- + * Displays multiple alerts + * @param array messageArray + * @param string severity (optional) defaults to 'info' + * @param string title (optional) defaults to 'Info' + * @param boolean sticky (optional) defaults to false + * @return void + * + * handleSystemError + * ----------------- + * Automatiticly determine how to display an system error and display it. + * This would be used in a catch block of an ajax call. + * @param mixed error + * @return void + * + * handleSystemMessage + * ------------------- + * Automatiticly determine how to display a message and display it. + * @param mixed message + * @return void + */ + +let toast_component = null; +const toast_queue = []; + +function _add_to_toast(...args) { + toast_component.add.apply(toast_component, args); +} +let toast_add = function _add_to_toast_queue(...args) { + toast_queue.push(args); +}; + +let alert_component = null; +const alert_queue = []; + +function _add_to_alert(...args) { + alert_component.add.apply(alert_component, args); +} +let alert_add = function _add_to_alert_queue(...args) { + alert_queue.push(args); +}; + +let confirm_component = null; +const confirm_queue = []; + +function _require_confirm(...args) { + confirm_component.confirm.apply(confirm_component, args); +} +let confirm_require = function _add_to_confirm_queue(...args) { + confirm_queue.push(args); +}; + + +const helperAppContainer = document.createElement('div'); + +const helperApp = Vue.createApp({ + setup() { + return self => { + return [ + Vue.h(primevue.toast, { + ref: 'toast', + baseZIndex: 99999 + }), + Vue.h(primevue.toast, { + ref: 'alert', + baseZIndex: 99999, + position: 'center', + }, { + message: slotProps => { + const messageCard = Vue.h('div', { + ref: 'messageCard', + id: 'collapseMessageCard', + class: 'collapse mt-3' + }, [ + Vue.h('div', {class: 'card card-body text-body small', style: 'white-space: pre-wrap'}, slotProps.message.detail) + ]); + return [ + Vue.h('i', {class: 'fa fa-circle-exclamation fa-2xl mt-3'}), + Vue.h('div', {class: 'p-toast-message-text'}, [ + Vue.h('span', {class: 'p-toast-summary'}, slotProps.message.summary), + Vue.h('div', {class: 'p-toast-detail my-3'}, 'Sorry! Ein interner technischer Fehler ist aufgetreten.'), + Vue.h('div', {class: 'd-flex justify-content-between align-items-center'}, [ + Vue.h('a', { + class: 'align-bottom flex-fill me-2', + dataBsToggle: 'collapse', + href: '#collapseMessageCard', + role: 'button', + ariaExpanded: 'false', + ariaControls: 'collapseMessageCard', + onClick: () => { bootstrap.Collapse.getOrCreateInstance(messageCard.el).toggle(); } + }, 'Fehler anzeigen'), + Vue.h('a', { + class: 'btn btn-primary flex-fill', + target: '_blank', + href: self.mailToUrl(slotProps), + }, 'Fehler melden') + ]), + messageCard, + ]), + ]; + } + }), + Vue.h(primevue.confirmdialog, { + ref: 'pvConfirmdialog' + }) + ]; + }; + }, + methods: { + mailToUrl(slotProps) { + let mailTo = 'noreply@technikum-wien.at'; // TODO domain anpassen + let subject = 'Meldung%20Systemfehler'; + let body = ` + Danke, dass Sie uns den Fehler melden. %0D%0A %0D%0A + Bitte beschreiben Sie uns ausführlich das Problem.%0D%0A + Bsp: Ich habe X ausgewählt und Y angelegt. Beim Speichern erhielt ich die Fehlermeldung. [Optional: Ich habe den Browser Z verwendet.]%0D%0A + -----------------------------------------------------------------------------------------------------------------------------------%0D%0A + PROBLEM: ... %0D%0A %0D%0A %0D%0A + + -----------------------------------------------------------------------------------------------------------------------------------%0D%0A + Fehler URL: ` + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method + `%0D%0A + Fehler Meldung: ` + slotProps.message.detail + `%0D%0A + -----------------------------------------------------------------------------------------------------------------------------------%0D%0A %0D%0A + Wir kümmern uns um eine rasche Behebung des Problems!` + + return "mailto:" + mailTo + "?subject=" + subject + "&body=" + body; + } + }, + mounted() { + toast_component = this.$refs.toast; + toast_add = _add_to_toast; + while (toast_queue.length) + _add_to_toast(toast_queue.unshift()); + + alert_component = this.$refs.alert; + alert_add = _add_to_alert; + while (alert_queue.length) + _add_to_alert(alert_queue.unshift()); + + confirm_component = this.$refs.confirm; + confirm_require = _require_confirm; + while (confirm_queue.length) + _require_confirm(confirm_queue.unshift()); + }, + beforeUnmount() { + toast_add = _add_to_toast_queue; + toast_component = null; + + alert_add = _add_to_alert_queue; + alert_component = null; + + confirm_require = _add_to_confirm_queue; + confirm_component = null; + }, + unmounted() { + helperAppContainer.parentElement.removeChild(helperAppContainer); + } +}); + +helperApp + .use(primevue.config.default) + .mount(helperAppContainer); + +document.body.appendChild(helperAppContainer); + +export default { + install: (app, options) => { + const $fhcAlert = { + alertSuccess(message) { + toast_add({ severity: 'success', summary: 'Info', detail: message, life: 1000}); + }, + alertInfo(message) { + toast_add({ severity: 'info', summary: 'Info', detail: message, life: 3000 }); + }, + alertWarning(message) { + toast_add({ severity: 'warn', summary: 'Achtung', detail: message, life: 7000 }); + }, + alertError(message) { + toast_add({ severity: 'error', summary: 'Achtung', detail: message }); + }, + alertSystemError(message) { + alert_add({ severity: 'error', summary: 'Systemfehler', detail: message}); + }, + confirmDelete() { + return new Promise((resolve, reject) => { + confirm_require({ + header: 'Achtung', + message: 'Möchten Sie sicher löschen?', + acceptLabel: 'Löschen', + acceptClass: 'btn btn-danger', + rejectLabel: 'Abbrechen', + rejectClass: 'btn btn-outline-secondary', + accept() { + resolve(true); + }, + reject() { + resolve(false); + }, + }); + }); + }, + alertDefault(severity, title, message, sticky = false) { + let options = { severity: severity, summary: title, detail: message}; + + if (!sticky) + options.life = 3000; + + toast_add(options); + }, + alertMultiple(messageArray, severity = 'info', title = 'Info', sticky = false){ + // Check, if array has only string values + if (messageArray.every(message => typeof message === 'string')) { + messageArray.every(message => this.alertDefault(severity, title, message, sticky)); + return true; + } + return false; + }, + handleSystemError(error) { + // Error is string + if (typeof error === 'string') + return $fhcAlert.alertSystemError(error); + + // Error is array of strings + if (Array.isArray(error) && error.every(err => typeof err === 'string')) + return error.every($fhcAlert.alertSystemError); + + // Error is object + if (typeof error === 'object' && error !== null) { + let errMsg = ''; + + if (error.hasOwnProperty('message')) + errMsg += 'Error Message: ' + error.message.toUpperCase() + '\r\n'; + + if (error.hasOwnProperty('config') && error.config.hasOwnProperty('url')) + errMsg += 'Error ConfigURL: ' + error.config.url + '\r\n'; + + if (error.hasOwnProperty('stack')) + errMsg += 'Error Stack: ' + error.stack + '\r\n'; + + // Fallback object error message + if (errMsg == '') + errMsg = 'Error Message: ' + JSON.stringify(error) + '\r\n'; + + errMsg += 'Error Controller Path: ' + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method; + + return $fhcAlert.alertSystemError(errMsg); + } + + // Fallback + $fhcAlert.alertSystemError('alertSystemError throws Generic Error\r\nError Controller Path: ' + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method); + }, + handleSystemMessage(message) { + // Message is string + if (typeof message === 'string') + return fhcerror.alertWarning(message); + + // Message is array of strings + if (Array.isArray(message)) { + // If Array has only Strings + if (message.every(msg => typeof msg === 'string')) + return message.every(fhcerror.alertWarning); + + // If Array has only Objects + if (message.every(msg => typeof msg === 'object') && msg !== null) { + return message.every(msg => { + if (msg.hasOwnProperty('data')) { + if (msg.data.hasOwnProperty('retval')) + fhcerror.alertWarning(JSON.stringify(msg.data.retval)); + // TODO(chris): there is no else here! join ifs? + } else { + fhcerror.alertSystemError(JSON.stringify(msg)); + } + }); + } + } + + // Message is Object with data property TODO: check object handling + if (typeof message === 'object' && message !== null){ + if (message.hasOwnProperty('data')) { + if (message.data.hasOwnProperty('retval')) + // NOTE(chris): changed: alertSystemError => alertWarning + fhcerror.alertWarning(JSON.stringify(message.data.retval)); + // TODO(chris): there is no else here! join ifs? + } else { + fhcerror.alertSystemError(JSON.stringify(message)); + } + return; + } + + // Fallback + fhcerror.alertSystemError('alertSystemError throws Generic Error\r\nError Controller Path: ' + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method); + } + }; + app.config.globalProperties.$fhcAlert = $fhcAlert; + } +} \ No newline at end of file From d57fd9eb609de807c823738d2391f5d13e473c0d Mon Sep 17 00:00:00 2001 From: cgfhtw Date: Tue, 24 Oct 2023 12:23:12 +0200 Subject: [PATCH 21/74] fhcAlert: slight improvements --- public/js/plugin/FhcAlert.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/public/js/plugin/FhcAlert.js b/public/js/plugin/FhcAlert.js index 5e1111dd6..8ff45f717 100644 --- a/public/js/plugin/FhcAlert.js +++ b/public/js/plugin/FhcAlert.js @@ -117,7 +117,7 @@ let confirm_component = null; const confirm_queue = []; function _require_confirm(...args) { - confirm_component.confirm.apply(confirm_component, args); + confirm_component.confirmListener.apply(confirm_component, args); } let confirm_require = function _add_to_confirm_queue(...args) { confirm_queue.push(args); @@ -174,7 +174,7 @@ const helperApp = Vue.createApp({ } }), Vue.h(primevue.confirmdialog, { - ref: 'pvConfirmdialog' + ref: 'confirm' }) ]; }; @@ -246,7 +246,7 @@ export default { toast_add({ severity: 'info', summary: 'Info', detail: message, life: 3000 }); }, alertWarning(message) { - toast_add({ severity: 'warn', summary: 'Achtung', detail: message, life: 7000 }); + toast_add({ severity: 'warn', summary: 'Achtung', detail: message}); }, alertError(message) { toast_add({ severity: 'error', summary: 'Achtung', detail: message }); @@ -336,10 +336,8 @@ export default { // If Array has only Objects if (message.every(msg => typeof msg === 'object') && msg !== null) { return message.every(msg => { - if (msg.hasOwnProperty('data')) { - if (msg.data.hasOwnProperty('retval')) - fhcerror.alertWarning(JSON.stringify(msg.data.retval)); - // TODO(chris): there is no else here! join ifs? + if (msg.hasOwnProperty('data') && msg.data.hasOwnProperty('retval')) { + fhcerror.alertWarning(JSON.stringify(msg.data.retval)); } else { fhcerror.alertSystemError(JSON.stringify(msg)); } @@ -347,13 +345,11 @@ export default { } } - // Message is Object with data property TODO: check object handling + // Message is Object with data property if (typeof message === 'object' && message !== null){ - if (message.hasOwnProperty('data')) { - if (message.data.hasOwnProperty('retval')) - // NOTE(chris): changed: alertSystemError => alertWarning - fhcerror.alertWarning(JSON.stringify(message.data.retval)); - // TODO(chris): there is no else here! join ifs? + if (message.hasOwnProperty('data') && message.data.hasOwnProperty('retval')) { + // NOTE(chris): changed: alertSystemError => alertWarning + fhcerror.alertWarning(JSON.stringify(message.data.retval)); } else { fhcerror.alertSystemError(JSON.stringify(message)); } From 22453c71b4aafe690ee386f2a1cf77a6b7e027b4 Mon Sep 17 00:00:00 2001 From: cgfhtw Date: Tue, 24 Oct 2023 13:35:50 +0200 Subject: [PATCH 22/74] fhcAlert: slight improvements 2 --- public/js/plugin/FhcAlert.js | 176 ++++++++++++----------------------- 1 file changed, 57 insertions(+), 119 deletions(-) diff --git a/public/js/plugin/FhcAlert.js b/public/js/plugin/FhcAlert.js index 8ff45f717..6ff54061d 100644 --- a/public/js/plugin/FhcAlert.js +++ b/public/js/plugin/FhcAlert.js @@ -93,91 +93,12 @@ * @return void */ -let toast_component = null; -const toast_queue = []; - -function _add_to_toast(...args) { - toast_component.add.apply(toast_component, args); -} -let toast_add = function _add_to_toast_queue(...args) { - toast_queue.push(args); -}; - -let alert_component = null; -const alert_queue = []; - -function _add_to_alert(...args) { - alert_component.add.apply(alert_component, args); -} -let alert_add = function _add_to_alert_queue(...args) { - alert_queue.push(args); -}; - -let confirm_component = null; -const confirm_queue = []; - -function _require_confirm(...args) { - confirm_component.confirmListener.apply(confirm_component, args); -} -let confirm_require = function _add_to_confirm_queue(...args) { - confirm_queue.push(args); -}; - - const helperAppContainer = document.createElement('div'); const helperApp = Vue.createApp({ - setup() { - return self => { - return [ - Vue.h(primevue.toast, { - ref: 'toast', - baseZIndex: 99999 - }), - Vue.h(primevue.toast, { - ref: 'alert', - baseZIndex: 99999, - position: 'center', - }, { - message: slotProps => { - const messageCard = Vue.h('div', { - ref: 'messageCard', - id: 'collapseMessageCard', - class: 'collapse mt-3' - }, [ - Vue.h('div', {class: 'card card-body text-body small', style: 'white-space: pre-wrap'}, slotProps.message.detail) - ]); - return [ - Vue.h('i', {class: 'fa fa-circle-exclamation fa-2xl mt-3'}), - Vue.h('div', {class: 'p-toast-message-text'}, [ - Vue.h('span', {class: 'p-toast-summary'}, slotProps.message.summary), - Vue.h('div', {class: 'p-toast-detail my-3'}, 'Sorry! Ein interner technischer Fehler ist aufgetreten.'), - Vue.h('div', {class: 'd-flex justify-content-between align-items-center'}, [ - Vue.h('a', { - class: 'align-bottom flex-fill me-2', - dataBsToggle: 'collapse', - href: '#collapseMessageCard', - role: 'button', - ariaExpanded: 'false', - ariaControls: 'collapseMessageCard', - onClick: () => { bootstrap.Collapse.getOrCreateInstance(messageCard.el).toggle(); } - }, 'Fehler anzeigen'), - Vue.h('a', { - class: 'btn btn-primary flex-fill', - target: '_blank', - href: self.mailToUrl(slotProps), - }, 'Fehler melden') - ]), - messageCard, - ]), - ]; - } - }), - Vue.h(primevue.confirmdialog, { - ref: 'confirm' - }) - ]; - }; + components: { + PvToast: primevue.toast, + PvConfirm: primevue.confirmdialog }, methods: { mailToUrl(slotProps) { @@ -197,66 +118,83 @@ const helperApp = Vue.createApp({ Wir kümmern uns um eine rasche Behebung des Problems!` return "mailto:" + mailTo + "?subject=" + subject + "&body=" + body; + }, + openMessagecard() { + bootstrap.Collapse.getOrCreateInstance(this.$refs.messageCard).toggle(); } }, - mounted() { - toast_component = this.$refs.toast; - toast_add = _add_to_toast; - while (toast_queue.length) - _add_to_toast(toast_queue.unshift()); - - alert_component = this.$refs.alert; - alert_add = _add_to_alert; - while (alert_queue.length) - _add_to_alert(alert_queue.unshift()); - - confirm_component = this.$refs.confirm; - confirm_require = _require_confirm; - while (confirm_queue.length) - _require_confirm(confirm_queue.unshift()); - }, - beforeUnmount() { - toast_add = _add_to_toast_queue; - toast_component = null; - - alert_add = _add_to_alert_queue; - alert_component = null; - - confirm_require = _add_to_confirm_queue; - confirm_component = null; - }, unmounted() { helperAppContainer.parentElement.removeChild(helperAppContainer); - } + }, + template: ` + + + + + ` }); -helperApp - .use(primevue.config.default) - .mount(helperAppContainer); +helperApp.use(primevue.config.default) +helperApp.use(primevue.confirmationservice) + +const helperAppInstance = helperApp.mount(helperAppContainer); document.body.appendChild(helperAppContainer); + export default { install: (app, options) => { const $fhcAlert = { alertSuccess(message) { - toast_add({ severity: 'success', summary: 'Info', detail: message, life: 1000}); + helperAppInstance.$refs.toast.add({ severity: 'success', summary: 'Info', detail: message, life: 1000}); }, alertInfo(message) { - toast_add({ severity: 'info', summary: 'Info', detail: message, life: 3000 }); + helperAppInstance.$refs.toast.add({ severity: 'info', summary: 'Info', detail: message, life: 3000 }); }, alertWarning(message) { - toast_add({ severity: 'warn', summary: 'Achtung', detail: message}); + helperAppInstance.$refs.toast.add({ severity: 'warn', summary: 'Achtung', detail: message}); }, alertError(message) { - toast_add({ severity: 'error', summary: 'Achtung', detail: message }); + helperAppInstance.$refs.toast.add({ severity: 'error', summary: 'Achtung', detail: message }); }, alertSystemError(message) { - alert_add({ severity: 'error', summary: 'Systemfehler', detail: message}); + helperAppInstance.$refs.alert.add({ severity: 'error', summary: 'Systemfehler', detail: message}); }, confirmDelete() { return new Promise((resolve, reject) => { - confirm_require({ + helperAppInstance.$confirm.require({ + group: 'fhcAlertConfirm', header: 'Achtung', message: 'Möchten Sie sicher löschen?', acceptLabel: 'Löschen', @@ -278,7 +216,7 @@ export default { if (!sticky) options.life = 3000; - toast_add(options); + helperAppInstance.$refs.toast.add(options); }, alertMultiple(messageArray, severity = 'info', title = 'Info', sticky = false){ // Check, if array has only string values From 6b2150b06694fa48842593bf12d19971419acdeb Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 25 Oct 2023 12:48:00 +0200 Subject: [PATCH 23/74] Fixed: unknown 'fhcerror' to this --- public/js/plugin/FhcAlert.js | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/public/js/plugin/FhcAlert.js b/public/js/plugin/FhcAlert.js index 6ff54061d..ababd0d34 100644 --- a/public/js/plugin/FhcAlert.js +++ b/public/js/plugin/FhcAlert.js @@ -263,21 +263,23 @@ export default { handleSystemMessage(message) { // Message is string if (typeof message === 'string') - return fhcerror.alertWarning(message); + { + return this.alertWarning(message); + } // Message is array of strings if (Array.isArray(message)) { // If Array has only Strings if (message.every(msg => typeof msg === 'string')) - return message.every(fhcerror.alertWarning); + return message.every(this.alertWarning); // If Array has only Objects if (message.every(msg => typeof msg === 'object') && msg !== null) { return message.every(msg => { if (msg.hasOwnProperty('data') && msg.data.hasOwnProperty('retval')) { - fhcerror.alertWarning(JSON.stringify(msg.data.retval)); + this.alertWarning(JSON.stringify(msg.data.retval)); } else { - fhcerror.alertSystemError(JSON.stringify(msg)); + this.alertSystemError(JSON.stringify(msg)); } }); } @@ -287,15 +289,15 @@ export default { if (typeof message === 'object' && message !== null){ if (message.hasOwnProperty('data') && message.data.hasOwnProperty('retval')) { // NOTE(chris): changed: alertSystemError => alertWarning - fhcerror.alertWarning(JSON.stringify(message.data.retval)); + this.alertWarning(JSON.stringify(message.data.retval)); } else { - fhcerror.alertSystemError(JSON.stringify(message)); + this.alertSystemError(JSON.stringify(message)); } return; } // Fallback - fhcerror.alertSystemError('alertSystemError throws Generic Error\r\nError Controller Path: ' + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method); + this.alertSystemError('alertSystemError throws Generic Error\r\nError Controller Path: ' + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method); } }; app.config.globalProperties.$fhcAlert = $fhcAlert; From c6d82fe029bb99c73ece04232caec2bd4eaf0198 Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 25 Oct 2023 12:49:37 +0200 Subject: [PATCH 24/74] Minor style change of confirmDelete message --- public/js/plugin/FhcAlert.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/js/plugin/FhcAlert.js b/public/js/plugin/FhcAlert.js index ababd0d34..21238c676 100644 --- a/public/js/plugin/FhcAlert.js +++ b/public/js/plugin/FhcAlert.js @@ -195,11 +195,12 @@ export default { return new Promise((resolve, reject) => { helperAppInstance.$confirm.require({ group: 'fhcAlertConfirm', - header: 'Achtung', + header: ' ', message: 'Möchten Sie sicher löschen?', acceptLabel: 'Löschen', acceptClass: 'btn btn-danger', rejectLabel: 'Abbrechen', + acceptIcon: 'fa fa-xmark', rejectClass: 'btn btn-outline-secondary', accept() { resolve(true); From fbb00be7cda562895ac7d4041a40911067f9d16a Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 25 Oct 2023 12:55:35 +0200 Subject: [PATCH 25/74] Added slot 'search' to Filterwidget.js Slot to inject a autoselect / inputfield to search tabulator, if tabulator should stay empty until search results are provided. (Example: performance reasons if too many data; search for multiple at once) --- public/js/components/filter/Filter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/js/components/filter/Filter.js b/public/js/components/filter/Filter.js index 16d8d4616..4e04ed4b4 100644 --- a/public/js/components/filter/Filter.js +++ b/public/js/components/filter/Filter.js @@ -580,7 +580,7 @@ export const CoreFilterCmpt = {
-
+
Mit {{selectedData.length}} ausgewählten: +
[ {{ filterName }} ] From 5a002c0f048c0c515d1abb24067514e7dc3480bb Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 31 Oct 2023 10:40:06 +0100 Subject: [PATCH 26/74] Minor change: Adapted mail-text --- public/js/plugin/FhcAlert.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/plugin/FhcAlert.js b/public/js/plugin/FhcAlert.js index 21238c676..e4aaddb73 100644 --- a/public/js/plugin/FhcAlert.js +++ b/public/js/plugin/FhcAlert.js @@ -106,7 +106,7 @@ const helperApp = Vue.createApp({ let subject = 'Meldung%20Systemfehler'; let body = ` Danke, dass Sie uns den Fehler melden. %0D%0A %0D%0A - Bitte beschreiben Sie uns ausführlich das Problem.%0D%0A + Bitte hängen Sie ein screenshot des Fehlers an und beschreiben Sie uns ausführlich das Problem.%0D%0A Bsp: Ich habe X ausgewählt und Y angelegt. Beim Speichern erhielt ich die Fehlermeldung. [Optional: Ich habe den Browser Z verwendet.]%0D%0A -----------------------------------------------------------------------------------------------------------------------------------%0D%0A PROBLEM: ... %0D%0A %0D%0A %0D%0A From c494dd1cdc938c9338b70dcfb78161f8a1d354f7 Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 31 Oct 2023 10:41:00 +0100 Subject: [PATCH 27/74] Added handleFormErrors- and resetFormErrors method to FhcAlert Plugin --- public/js/plugin/FhcAlert.js | 59 ++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/public/js/plugin/FhcAlert.js b/public/js/plugin/FhcAlert.js index e4aaddb73..d07ed0d47 100644 --- a/public/js/plugin/FhcAlert.js +++ b/public/js/plugin/FhcAlert.js @@ -299,6 +299,65 @@ export default { // Fallback this.alertSystemError('alertSystemError throws Generic Error\r\nError Controller Path: ' + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method); + }, + handleFormErrors(errors, formRef){ + // Reset previous error messages, if present + this.resetFormErrors(formRef); + + // If errors is object + if (typeof errors === 'object' && !Array.isArray(errors) && errors !== null) + { + // Loop through errors + for (let key in errors) { + + let input = formRef.querySelector('[name="' + key + '"]'); + + // If key is an input field name, display error above field + if (input) { + input.classList.add("is-invalid"); + input.classList.add("form-control"); + + const feedback = document.createElement("div"); + feedback.innerHTML = errors[key]; + feedback.classList.add("invalid-feedback"); + + input.after(feedback); + } + // ...else display error on top of the form + else { + const feedback = document.createElement("div"); + feedback.classList.add("d-flex"); + feedback.classList.add("align-items-center"); + feedback.classList.add("alert"); + feedback.classList.add("alert-danger"); + feedback.innerHTML = errors[key]; + + formRef.prepend(feedback); + } + } + } + // else, display on top of the form + else { + const feedback = document.createElement("div"); + feedback.classList.add("d-flex"); + feedback.classList.add("align-items-center"); + feedback.classList.add("alert"); + feedback.classList.add("alert-danger"); + feedback.innerHTML = errors; + + formRef.prepend(feedback); + } + }, + resetFormErrors(formRef){ + // Remove all errors above input fields + Array.from(formRef.getElementsByClassName('is-invalid')).forEach(el => el.classList.remove('is-invalid')); + Array.from(formRef.getElementsByClassName('invalid-feedback')).forEach(el => el.remove()); + + // Check if there is a prepended alert-danger div, and remove it if it exists + const prependedAlert = formRef.querySelector('.alert.alert-danger'); + if (prependedAlert) { + prependedAlert.remove(); + } } }; app.config.globalProperties.$fhcAlert = $fhcAlert; From 6140e15139e56765f41414e16a1f9fa79d0e80e1 Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 13 Feb 2024 14:50:26 +0100 Subject: [PATCH 28/74] Removed unused tabulatorAdditionalColumns property. Instead additional cols like 'action buttons' are now checked by index. --- public/js/components/filter/Filter.js | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/public/js/components/filter/Filter.js b/public/js/components/filter/Filter.js index efb24fb57..69b64d383 100644 --- a/public/js/components/filter/Filter.js +++ b/public/js/components/filter/Filter.js @@ -55,8 +55,6 @@ export const CoreFilterCmpt = { }, tabulatorOptions: Object, tabulatorEvents: Array, - // TODO check to remove - tabulatorAdditionalColumns: Array, tableOnly: Boolean, reload: Boolean, download: { @@ -141,15 +139,12 @@ export const CoreFilterCmpt = { for (let col of columns) { // If the column has to be displayed or not - col.visible = selectedFields.indexOf(col.field) >= 0; - // TODO additionalCols wieder löschen? - // if (col.formatter == 'rowSelection') - // col.visible = true; - if ( - col.formatter == 'rowSelection' - || (this.tabulatorAdditionalColumns && this.tabulatorAdditionalColumns.indexOf(col.field) >= 0) - ) + /* fields.indexOf(col.field) == -1; ensures displaying formatter colums + e.g. column with rowSelection checkboxes or with custom formatted action buttons */ + col.visible = selectedFields.indexOf(col.field) >= 0 || fields.indexOf(col.field) == -1; + if (col.formatter == 'rowSelection') + col.visible = true; if (col.hasOwnProperty('resizable')) col.resizable = col.visible; From 8f81426fa4e7d1c32c94183ff72dbd9e45d0b72d Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 13 Feb 2024 14:54:42 +0100 Subject: [PATCH 29/74] Corrected error when using alertMultiple and handleSystemMessage --- public/js/plugin/FhcAlert.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/public/js/plugin/FhcAlert.js b/public/js/plugin/FhcAlert.js index 079039aed..307064d76 100644 --- a/public/js/plugin/FhcAlert.js +++ b/public/js/plugin/FhcAlert.js @@ -237,7 +237,7 @@ export default { alertMultiple(messageArray, severity = 'info', title = 'Info', sticky = false){ // Check, if array has only string values if (messageArray.every(message => typeof message === 'string')) { - messageArray.every(message => this.alertDefault(severity, title, message, sticky)); + messageArray.forEach(message => this.alertDefault(severity, title, message, sticky)); return true; } return false; @@ -281,21 +281,24 @@ export default { handleSystemMessage(message) { // Message is string if (typeof message === 'string') - return fhcerror.alertWarning(message); + return $fhcAlert.alertWarning(message); // Message is array of strings if (Array.isArray(message)) { // If Array has only Strings if (message.every(msg => typeof msg === 'string')) - return message.every(fhcerror.alertWarning); + return message.every($fhcAlert.alertWarning); // If Array has only Objects if (message.every(msg => typeof msg === 'object') && msg !== null) { return message.every(msg => { if (msg.hasOwnProperty('data') && msg.data.hasOwnProperty('retval')) { - fhcerror.alertWarning(JSON.stringify(msg.data.retval)); + $fhcAlert.alertWarning(JSON.stringify(msg.data.retval)); } else { - fhcerror.alertSystemError(JSON.stringify(msg)); + console.log('FhcAlert systemError'); + console.log(msg); + console.log(JSON.stringify(msg)); + $fhcAlert.alertSystemError(JSON.stringify(msg)); } }); } @@ -305,15 +308,15 @@ export default { if (typeof message === 'object' && message !== null){ if (message.hasOwnProperty('data') && message.data.hasOwnProperty('retval')) { // NOTE(chris): changed: alertSystemError => alertWarning - fhcerror.alertWarning(JSON.stringify(message.data.retval)); + $fhcAlert.alertWarning(JSON.stringify(message.data.retval)); } else { - fhcerror.alertSystemError(JSON.stringify(message)); + $fhcAlert.alertSystemError(JSON.stringify(message)); } return; } // Fallback - fhcerror.alertSystemError('alertSystemError throws Generic Error\r\nError Controller Path: ' + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method); + $fhcAlert.alertSystemError('alertSystemError throws Generic Error\r\nError Controller Path: ' + FHC_JS_DATA_STORAGE_OBJECT.called_path + '/' + FHC_JS_DATA_STORAGE_OBJECT.called_method); }, resetFormValidation(form) { const event = new Event('fhc-form-reset'); From 7a6d095b780e426bc3fefda216317d8a740e6c2e Mon Sep 17 00:00:00 2001 From: Werner Masik Date: Thu, 29 Feb 2024 17:09:59 +0100 Subject: [PATCH 30/74] create db tables for fristenmanagement --- .../dbupdate_3.4/37107_fristenmanagement.php | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 system/dbupdate_3.4/37107_fristenmanagement.php diff --git a/system/dbupdate_3.4/37107_fristenmanagement.php b/system/dbupdate_3.4/37107_fristenmanagement.php new file mode 100644 index 000000000..84b828008 --- /dev/null +++ b/system/dbupdate_3.4/37107_fristenmanagement.php @@ -0,0 +1,62 @@ +db_query("SELECT * FROM information_schema.tables WHERE table_name='tbl_dienstverhaeltnis' AND table_schema='hr'")) +{ + if ($db->db_num_rows($result) == 0) + { + $qry = " + CREATE TABLE IF NOT EXISTS hr.tbl_frist ( + frist_id bigserial NOT NULL, + mitarbeiter_uid character varying(32) NOT NULL, + ereignis_kurzbz character varying(32) NOT NULL, + bezeichnung varchar(255), + datum date, + status_kurzbz character varying(32) NOT NULL, + parameter jsonb NOT NULL, + insertvon character varying(32) NOT NULL, + insertamum timestamp without time zone DEFAULT now() NOT NULL, + updatevon character varying(32), + updateamum timestamp without time zone, + CONSTRAINT tbl_frist_pkey PRIMARY KEY (frist_id) + ); + + CREATE TABLE IF NOT EXISTS hr.tbl_frist_ereignis ( + ereignis_kurzbz character varying(32) NOT NULL, + bezeichnung varchar(32) NOT NULL, + manuell boolean DEFAULT FALSE, + CONSTRAINT tbl_ereignis_pkey PRIMARY KEY (ereignis_kurzbz) + ); + + COMMENT ON TABLE hr.tbl_frist_status IS E'Key-Table of fristen (deadline) events'; + + CREATE TABLE IF NOT EXISTS hr.tbl_frist_status + status_kurzbz character varying(32) NOT NULL, + bezeichnung varchar(32), + CONSTRAINT tbl_frist_status_pk PRIMARY KEY (status_kurzbz) + ); + + COMMENT ON TABLE hr.tbl_frist_status IS E'Key-Table of fristen status (new, done)'; + + ALTER TABLE hr.tbl_frist ADD CONSTRAINT hr.tbl_frist_mitarbeiter_uid_fk FOREIGN KEY (mitarbeiter_uid) + REFERENCES public.tbl_mitarbeiter (mitarbeiter_uid) MATCH FULL + ON DELETE SET NULL ON UPDATE CASCADE; + + ALTER TABLE hr.tbl_frist ADD CONSTRAINT hr.tbl_frist_ereignis_kurzbz_fk FOREIGN KEY (ereignis_kurzbz) + REFERENCES hr.tbl_frist_ereignis (ereignis_kurzbz) MATCH FULL + ON DELETE SET NULL ON UPDATE CASCADE; + + ALTER TABLE hr.tbl_frist ADD CONSTRAINT hr.tbl_frist_status_kurzbz_fk FOREIGN KEY (status_kurzbz) + REFERENCES hr.tbl_frist_status (status_kurzbz) MATCH FULL + ON DELETE SET NULL ON UPDATE CASCADE; + + + + "; + + if (! $db->db_query($qry)) + echo 'Fristenmanagement: ' . $db->db_last_error() . '
'; + else + echo 'Fristenmanagementtabellen wurden neu erstellt'; + } +} From c60f7ed8b0e467644299be9233cf8e8adee1cf3a Mon Sep 17 00:00:00 2001 From: Werner Masik Date: Fri, 1 Mar 2024 15:43:15 +0100 Subject: [PATCH 31/74] dbUpdate for fristenmanagement completed --- system/dbupdate_3.4.php | 4 ++++ .../dbupdate_3.4/37107_fristenmanagement.php | 20 ++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/system/dbupdate_3.4.php b/system/dbupdate_3.4.php index c8669de28..d32185c6e 100644 --- a/system/dbupdate_3.4.php +++ b/system/dbupdate_3.4.php @@ -49,6 +49,7 @@ require_once('dbupdate_3.4/30181_tabelle_anrechnung_neue_attribute_fuer_begruend require_once('dbupdate_3.4/29529_infocenter_anpassungen.php'); require_once('dbupdate_3.4/29835_uhstat1_erfassung_der_uhstat1_daten_ueber_das_bewerbungstool.php'); require_once('dbupdate_3.4/33714_erhoehter_studienbeitrag_fuer_drittsaatenangehoerig.php'); +require_once('dbupdate_3.4/37107_fristenmanagement.php'); // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen @@ -176,6 +177,9 @@ $tabellen=array( "hr.tbl_gehaltsbestandteil" => array("gehaltsbestandteil_id","dienstverhaeltnis_id","vertragsbestandteil_id","gehaltstyp_kurzbz","von","bis","anmerkung","grundbetrag","betrag_valorisiert","valorisierungssperre","insertamum", "insertvon","updateamum","updatevon","valorisierung","auszahlungen"), "hr.tbl_gehaltshistorie" => array("gehaltshistorie_id", "datum","betrag","gehaltsbestandteil_id","mitarbeiter_uid"), "hr.tbl_gehaltstyp" => array("gehaltstyp_kurzbz","bezeichnung","valorisierung","sort","aktiv"), + "hr.tbl_frist" => array("frist_id","mitarbeiter_uid","ereignis_kurzbz","bezeichnung","datum","status_kurzbz","parameter","insertvon","insertamum","updatevon","updateamum"), + "hr.tbl_frist_ereignis" => array("ereignis_kurzbz","bezeichnung","manuell"), + "hr.tbl_frist_status" => array("status_kurzbz", "bezeichnung"), "lehre.tbl_abschlussbeurteilung" => array("abschlussbeurteilung_kurzbz","bezeichnung","bezeichnung_english","sort"), "lehre.tbl_abschlusspruefung" => array("abschlusspruefung_id","student_uid","vorsitz","pruefer1","pruefer2","pruefer3","abschlussbeurteilung_kurzbz","akadgrad_id","pruefungstyp_kurzbz","datum","uhrzeit","sponsion","anmerkung","updateamum","updatevon","insertamum","insertvon","ext_id","note","protokoll","endezeit","pruefungsantritt_kurzbz","freigabedatum"), "lehre.tbl_abschlusspruefung_antritt" => array("pruefungsantritt_kurzbz","bezeichnung","bezeichnung_english","sort"), diff --git a/system/dbupdate_3.4/37107_fristenmanagement.php b/system/dbupdate_3.4/37107_fristenmanagement.php index 84b828008..678f41d67 100644 --- a/system/dbupdate_3.4/37107_fristenmanagement.php +++ b/system/dbupdate_3.4/37107_fristenmanagement.php @@ -28,9 +28,9 @@ if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table CONSTRAINT tbl_ereignis_pkey PRIMARY KEY (ereignis_kurzbz) ); - COMMENT ON TABLE hr.tbl_frist_status IS E'Key-Table of fristen (deadline) events'; + COMMENT ON TABLE hr.tbl_frist_ereignis IS E'Key-Table of fristen (deadline) events'; - CREATE TABLE IF NOT EXISTS hr.tbl_frist_status + CREATE TABLE IF NOT EXISTS hr.tbl_frist_status ( status_kurzbz character varying(32) NOT NULL, bezeichnung varchar(32), CONSTRAINT tbl_frist_status_pk PRIMARY KEY (status_kurzbz) @@ -38,18 +38,28 @@ if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table COMMENT ON TABLE hr.tbl_frist_status IS E'Key-Table of fristen status (new, done)'; - ALTER TABLE hr.tbl_frist ADD CONSTRAINT hr.tbl_frist_mitarbeiter_uid_fk FOREIGN KEY (mitarbeiter_uid) + ALTER TABLE hr.tbl_frist ADD CONSTRAINT tbl_frist_mitarbeiter_uid_fk FOREIGN KEY (mitarbeiter_uid) REFERENCES public.tbl_mitarbeiter (mitarbeiter_uid) MATCH FULL ON DELETE SET NULL ON UPDATE CASCADE; - ALTER TABLE hr.tbl_frist ADD CONSTRAINT hr.tbl_frist_ereignis_kurzbz_fk FOREIGN KEY (ereignis_kurzbz) + ALTER TABLE hr.tbl_frist ADD CONSTRAINT tbl_frist_ereignis_kurzbz_fk FOREIGN KEY (ereignis_kurzbz) REFERENCES hr.tbl_frist_ereignis (ereignis_kurzbz) MATCH FULL ON DELETE SET NULL ON UPDATE CASCADE; - ALTER TABLE hr.tbl_frist ADD CONSTRAINT hr.tbl_frist_status_kurzbz_fk FOREIGN KEY (status_kurzbz) + ALTER TABLE hr.tbl_frist ADD CONSTRAINT tbl_frist_status_kurzbz_fk FOREIGN KEY (status_kurzbz) REFERENCES hr.tbl_frist_status (status_kurzbz) MATCH FULL ON DELETE SET NULL ON UPDATE CASCADE; + GRANT SELECT, UPDATE, INSERT, DELETE ON hr.tbl_frist TO vilesci; + GRANT SELECT, UPDATE, INSERT, DELETE ON hr.tbl_frist_status TO vilesci; + GRANT SELECT, UPDATE, INSERT, DELETE ON hr.tbl_frist_ereignis TO vilesci; + + INSERT INTO hr.tbl_frist_status(status_kurzbz, bezeichnung) VALUES('neu','Neu'); + INSERT INTO hr.tbl_frist_status(status_kurzbz, bezeichnung) VALUES('erledigt','Erledigt'); + + INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung) VALUES('dv_beginn','DV Beginn'); + INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung) VALUES('dv_ende','DV Ende'); + "; From 77666e5210d7616453bd69390b5a2183f4b169c0 Mon Sep 17 00:00:00 2001 From: Werner Masik Date: Wed, 6 Mar 2024 08:27:39 +0100 Subject: [PATCH 32/74] added column verantwortlich_uid --- system/dbupdate_3.4/37107_fristenmanagement.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/system/dbupdate_3.4/37107_fristenmanagement.php b/system/dbupdate_3.4/37107_fristenmanagement.php index 678f41d67..d63bae80d 100644 --- a/system/dbupdate_3.4/37107_fristenmanagement.php +++ b/system/dbupdate_3.4/37107_fristenmanagement.php @@ -8,7 +8,8 @@ if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table $qry = " CREATE TABLE IF NOT EXISTS hr.tbl_frist ( frist_id bigserial NOT NULL, - mitarbeiter_uid character varying(32) NOT NULL, + mitarbeiter_uid character varying(32), + verantwortlich_uid character varying(32), ereignis_kurzbz character varying(32) NOT NULL, bezeichnung varchar(255), datum date, @@ -42,6 +43,10 @@ if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table REFERENCES public.tbl_mitarbeiter (mitarbeiter_uid) MATCH FULL ON DELETE SET NULL ON UPDATE CASCADE; + ALTER TABLE hr.tbl_frist ADD CONSTRAINT tbl_frist_verantwortlich_uid_fk FOREIGN KEY (verantwortlich_uid) + REFERENCES public.tbl_mitarbeiter (mitarbeiter_uid) MATCH FULL + ON DELETE SET NULL ON UPDATE CASCADE; + ALTER TABLE hr.tbl_frist ADD CONSTRAINT tbl_frist_ereignis_kurzbz_fk FOREIGN KEY (ereignis_kurzbz) REFERENCES hr.tbl_frist_ereignis (ereignis_kurzbz) MATCH FULL ON DELETE SET NULL ON UPDATE CASCADE; @@ -55,6 +60,7 @@ if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table GRANT SELECT, UPDATE, INSERT, DELETE ON hr.tbl_frist_ereignis TO vilesci; INSERT INTO hr.tbl_frist_status(status_kurzbz, bezeichnung) VALUES('neu','Neu'); + INSERT INTO hr.tbl_frist_status(status_kurzbz, bezeichnung) VALUES('in_bearbeitung','In Bearbeitung'); INSERT INTO hr.tbl_frist_status(status_kurzbz, bezeichnung) VALUES('erledigt','Erledigt'); INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung) VALUES('dv_beginn','DV Beginn'); From e28627a676d78bfc25ba0b82a55db1c5e9deddb7 Mon Sep 17 00:00:00 2001 From: Werner Masik Date: Tue, 12 Mar 2024 17:34:13 +0100 Subject: [PATCH 33/74] removed verantwortlich column from tbl_frist --- system/dbupdate_3.4/37107_fristenmanagement.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/system/dbupdate_3.4/37107_fristenmanagement.php b/system/dbupdate_3.4/37107_fristenmanagement.php index d63bae80d..68811fd18 100644 --- a/system/dbupdate_3.4/37107_fristenmanagement.php +++ b/system/dbupdate_3.4/37107_fristenmanagement.php @@ -1,15 +1,14 @@ db_query("SELECT * FROM information_schema.tables WHERE table_name='tbl_dienstverhaeltnis' AND table_schema='hr'")) +if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table_name='tbl_frist' AND table_schema='hr'")) { if ($db->db_num_rows($result) == 0) { $qry = " CREATE TABLE IF NOT EXISTS hr.tbl_frist ( frist_id bigserial NOT NULL, - mitarbeiter_uid character varying(32), - verantwortlich_uid character varying(32), + mitarbeiter_uid character varying(32), ereignis_kurzbz character varying(32) NOT NULL, bezeichnung varchar(255), datum date, @@ -43,10 +42,6 @@ if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table REFERENCES public.tbl_mitarbeiter (mitarbeiter_uid) MATCH FULL ON DELETE SET NULL ON UPDATE CASCADE; - ALTER TABLE hr.tbl_frist ADD CONSTRAINT tbl_frist_verantwortlich_uid_fk FOREIGN KEY (verantwortlich_uid) - REFERENCES public.tbl_mitarbeiter (mitarbeiter_uid) MATCH FULL - ON DELETE SET NULL ON UPDATE CASCADE; - ALTER TABLE hr.tbl_frist ADD CONSTRAINT tbl_frist_ereignis_kurzbz_fk FOREIGN KEY (ereignis_kurzbz) REFERENCES hr.tbl_frist_ereignis (ereignis_kurzbz) MATCH FULL ON DELETE SET NULL ON UPDATE CASCADE; From 426a43955247d8b7e3ad1ae09881186886b75608 Mon Sep 17 00:00:00 2001 From: Werner Masik Date: Wed, 20 Mar 2024 00:13:55 +0100 Subject: [PATCH 34/74] added sort column to frist --- .../dbupdate_3.4/37107_fristenmanagement.php | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/system/dbupdate_3.4/37107_fristenmanagement.php b/system/dbupdate_3.4/37107_fristenmanagement.php index 68811fd18..eeb32380e 100644 --- a/system/dbupdate_3.4/37107_fristenmanagement.php +++ b/system/dbupdate_3.4/37107_fristenmanagement.php @@ -25,6 +25,7 @@ if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table ereignis_kurzbz character varying(32) NOT NULL, bezeichnung varchar(32) NOT NULL, manuell boolean DEFAULT FALSE, + sort smallint, CONSTRAINT tbl_ereignis_pkey PRIMARY KEY (ereignis_kurzbz) ); @@ -33,6 +34,7 @@ if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table CREATE TABLE IF NOT EXISTS hr.tbl_frist_status ( status_kurzbz character varying(32) NOT NULL, bezeichnung varchar(32), + sort smallint, CONSTRAINT tbl_frist_status_pk PRIMARY KEY (status_kurzbz) ); @@ -54,13 +56,19 @@ if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table GRANT SELECT, UPDATE, INSERT, DELETE ON hr.tbl_frist_status TO vilesci; GRANT SELECT, UPDATE, INSERT, DELETE ON hr.tbl_frist_ereignis TO vilesci; - INSERT INTO hr.tbl_frist_status(status_kurzbz, bezeichnung) VALUES('neu','Neu'); - INSERT INTO hr.tbl_frist_status(status_kurzbz, bezeichnung) VALUES('in_bearbeitung','In Bearbeitung'); - INSERT INTO hr.tbl_frist_status(status_kurzbz, bezeichnung) VALUES('erledigt','Erledigt'); - - INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung) VALUES('dv_beginn','DV Beginn'); - INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung) VALUES('dv_ende','DV Ende'); + INSERT INTO hr.tbl_frist_status(status_kurzbz, bezeichnung, sort) VALUES('neu','Neu', 1); + INSERT INTO hr.tbl_frist_status(status_kurzbz, bezeichnung, sort) VALUES('in_bearbeitung','In Bearbeitung', 2); + INSERT INTO hr.tbl_frist_status(status_kurzbz, bezeichnung, sort) VALUES('erledigt','Erledigt', 3); + INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung, sort) VALUES('dv_beginn','DV Beginn', 1); + INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung, sort) VALUES('dv_ende','DV Ende', 2); + INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung, sort) VALUES('stunden_beginn','Stunden Beginn', 3); + INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung, sort) VALUES('stunden_ende','Stunden Ende', 4); + INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung, sort) VALUES('karenz_beginn','Karenz Beginn', 5); + INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung, sort) VALUES('karenz_ende','Karenz Ende', 6); + INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung, sort) VALUES('zeitaufzeichnung_beginn','Zeitaufzeichnung Beginn', 7); + INSERT INTO hr.tbl_frist_ereignis(ereignis_kurzbz, bezeichnung, sort) VALUES('zeitaufzeichnung_ende','Zeitaufzeichnung Ende', 8); + INSERT INTO hr.tbl_frist_ereignis (ereignis_kurzbz , bezeichnung, manuell, sort) VALUES('manuell','Manuell', true, 9); "; From 10e57dae2de4ec405964059ef33b8792931f8307 Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 20 Mar 2024 09:38:08 +0100 Subject: [PATCH 35/74] Adapted style of .tabulator-cell .btn to be squared and increased padding --- public/css/Tabulator5.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/css/Tabulator5.css b/public/css/Tabulator5.css index b755f0d76..49e15ab37 100644 --- a/public/css/Tabulator5.css +++ b/public/css/Tabulator5.css @@ -40,7 +40,7 @@ } .tabulator-cell .btn { - padding: 0 .5rem; - max-height: 22px; - min-width: 30px; + padding: 0 .7rem; + min-height: 25px; + min-width: 25px; } From 842e62b0dd4ae5173f97a816e9fc2d610958ff92 Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 20 Mar 2024 09:42:23 +0100 Subject: [PATCH 36/74] Fixed Input.js error causing to keep last entries' first letter in form inputs, even when formdata was emptied --- public/js/components/Form/Input.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/js/components/Form/Input.js b/public/js/components/Form/Input.js index 11ad357a5..b4f87f501 100644 --- a/public/js/components/Form/Input.js +++ b/public/js/components/Form/Input.js @@ -160,12 +160,12 @@ export default { }, modelValueCmp: { get() { - if (this.$attrs.modelValue === undefined) + if (!this.$attrs.hasOwnProperty('modelValue')) return this.modelValueDummy; return this.$attrs.modelValue; }, set(v) { - if (this.$attrs.modelValue === undefined) + if (!this.$attrs.hasOwnProperty('modelValue')) this.modelValueDummy = v; this.$emit('update:modelValue', v); } From 6eae83f4eba76848ca63eae121de16d43d72dc43 Mon Sep 17 00:00:00 2001 From: Cris Date: Wed, 20 Mar 2024 09:45:25 +0100 Subject: [PATCH 37/74] Added primevues autocomplete slot template to Input.js Now, when using the Input Component with type 'autocomplete', it is possible to add also primevues built in slot templates there --- public/js/components/Form/Input.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/public/js/components/Form/Input.js b/public/js/components/Form/Input.js index b4f87f501..ccd7e856d 100644 --- a/public/js/components/Form/Input.js +++ b/public/js/components/Form/Input.js @@ -242,6 +242,7 @@ export default { + + + + + + + + + + + + Date: Wed, 20 Mar 2024 09:52:26 +0100 Subject: [PATCH 38/74] Added label property 'class' to Input.js ...which fixes style issues when creating input-group buttons using the Input.js component --- public/js/components/Form/Input.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/js/components/Form/Input.js b/public/js/components/Form/Input.js index ccd7e856d..0940701a5 100644 --- a/public/js/components/Form/Input.js +++ b/public/js/components/Form/Input.js @@ -236,7 +236,7 @@ export default { }, template: ` - +