From 52a55a018c0d72fd8e5352592dd1ee7fb5309618 Mon Sep 17 00:00:00 2001 From: Johann Hoffmann Date: Mon, 10 Jun 2024 15:13:30 +0200 Subject: [PATCH] merge fix --- public/js/components/filter/Filter.js | 185 +++++++++++++++++--------- public/js/plugin/FhcApi.js | 84 ++++++++---- system/dbupdate_3.4.php | 60 ++++----- 3 files changed, 213 insertions(+), 116 deletions(-) diff --git a/public/js/components/filter/Filter.js b/public/js/components/filter/Filter.js index 64a75c910..b49e408c0 100644 --- a/public/js/components/filter/Filter.js +++ b/public/js/components/filter/Filter.js @@ -15,8 +15,6 @@ * along with this program. If not, see . */ -import {CoreFilterAPIs} from './API.js'; -import {CoreRESTClient} from '../../RESTClient.js'; import {CoreFetchCmpt} from '../../components/Fetch.js'; import FilterConfig from './Filter/Config.js'; import FilterColumns from './Filter/Columns.js'; @@ -64,7 +62,11 @@ export const CoreFilterCmpt = { newBtnShow: Boolean, newBtnClass: [String, Array, Object], newBtnDisabled: Boolean, - newBtnLabel: String + newBtnLabel: String, + uniqueId: String, + // TODO soll im master kommen? + idField: String, + parentIdField: String }, data: function() { return { @@ -193,16 +195,16 @@ export const CoreFilterCmpt = { } // Define a default tabulator options in case it was not provided let tabulatorOptions = {...{ - height: 500, - layout: "fitDataStretch", - movableColumns: true, - columnDefaults:{ - tooltip: true, - }, - placeholder, - reactiveData: true, - persistence: true - }, ...(this.tabulatorOptions || {})}; + height: 500, + layout: "fitDataStretch", + movableColumns: true, + columnDefaults:{ + tooltip: true, + }, + placeholder, + reactiveData: true, + persistence: true + }, ...(this.tabulatorOptions || {})}; if (!this.tableOnly) { tabulatorOptions.data = this.filteredData; @@ -211,6 +213,13 @@ export const CoreFilterCmpt = { if (tabulatorOptions.columns && tabulatorOptions.columns.filter(el => el.formatter == 'rowSelection').length) this.tabulatorHasSelector = true; + // TODO check ob im core bleiben soll + 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( @@ -228,6 +237,33 @@ export const CoreFilterCmpt = { this.tabulator.on("rowSelectionChanged", data => { this.selectedData = data; }); + // TODO check ob im core so bleiben soll + // 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(); @@ -252,12 +288,12 @@ export const CoreFilterCmpt = { /** * */ - getFilter: function() { + getFilter() { if (this.selectedFilter === null) - this.startFetchCmpt(CoreFilterAPIs.getFilter, null, this.render); + this.startFetchCmpt(this.$fhcApi.factory.filter.getFilter, null, this.render); else this.startFetchCmpt( - CoreFilterAPIs.getFilterById, + this.$fhcApi.factory.filter.getFilterById, { filterId: this.selectedFilter }, @@ -267,55 +303,47 @@ export const CoreFilterCmpt = { /** * */ - render: function(response) { + render(response) { + let data = response; + this.filterName = data.filterName; + this.dataset = data.dataset; + this.datasetMetadata = data.datasetMetadata; - if (CoreRESTClient.hasData(response)) + this.fields = data.fields; + this.selectedFields = data.selectedFields; + this.notSelectedFields = this.fields.filter(x => this.selectedFields.indexOf(x) === -1); + this.filterFields = []; + + for (let i = 0; i < data.datasetMetadata.length; i++) { - let data = CoreRESTClient.getData(response); - this.filterName = data.filterName; - this.dataset = data.dataset; - this.datasetMetadata = data.datasetMetadata; - - this.fields = data.fields; - this.selectedFields = data.selectedFields; - this.notSelectedFields = this.fields.filter(x => this.selectedFields.indexOf(x) === -1); - this.filterFields = []; - - for (let i = 0; i < data.datasetMetadata.length; i++) + for (let j = 0; j < data.filters.length; j++) { - for (let j = 0; j < data.filters.length; j++) + if (data.datasetMetadata[i].name == data.filters[j].name) { - if (data.datasetMetadata[i].name == data.filters[j].name) - { - let filter = data.filters[j]; - filter.type = data.datasetMetadata[i].type; + let filter = data.filters[j]; + filter.type = data.datasetMetadata[i].type; - this.filterFields.push(filter); - //break; - } + this.filterFields.push(filter); + //break; } } + } - // If the side menu is active - if (this.sideMenu === true) - { - this.setSideMenu(data); - } - else // otherwise use the dropdown in the filter options - { - this.setDropDownMenu(data); - } - this.updateTabulator(); - } - else + // If the side menu is active + if (this.sideMenu === true) { - console.error(CoreRESTClient.getError(response)); + this.setSideMenu(data); } + else // otherwise use the dropdown in the filter options + { + this.setDropDownMenu(data); + } + this.updateTabulator(); }, /** * Set the menu */ - setSideMenu: function(data) { + setSideMenu(data) { let filters = data.sideMenu.filters; let personalFilters = data.sideMenu.personalFilters; let filtersArray = []; @@ -369,7 +397,7 @@ export const CoreFilterCmpt = { /** * Set the drop down menu */ - setDropDownMenu: function(data) { + setDropDownMenu(data) { let filters = data.sideMenu.filters; let personalFilters = data.sideMenu.personalFilters; let filtersArray = []; @@ -405,7 +433,7 @@ export const CoreFilterCmpt = { /** * Used to start/refresh the FetchCmpt */ - startFetchCmpt: function(apiFunction, apiFunctionParameters, dataFetchedCallback) { + startFetchCmpt(apiFunction, apiFunctionParameters, dataFetchedCallback) { // Assign the function api of the FetchCmpt binded property this.fetchCmptApiFunction = apiFunction; @@ -416,6 +444,9 @@ export const CoreFilterCmpt = { apiFunctionParameters.filterUniqueId = FHC_JS_DATA_STORAGE_OBJECT.called_path + "/" + FHC_JS_DATA_STORAGE_OBJECT.called_method; apiFunctionParameters.filterType = this.filterType; + if (this.uniqueId) + apiFunctionParameters.filterUniqueId += '_' + this.uniqueId; + // Assign parameters to the FetchCmpt binded properties this.fetchCmptApiFunctionParams = apiFunctionParameters; // Assign data fetch callback to the FetchCmpt binded properties @@ -431,11 +462,11 @@ export const CoreFilterCmpt = { /** * */ - handlerSaveCustomFilter: function(customFilterName) { + handlerSaveCustomFilter(customFilterName) { this.selectedFilter = null; // this.startFetchCmpt( - CoreFilterAPIs.saveCustomFilter, + this.$fhcApi.factory.filter.saveCustomFilter, { customFilterName }, @@ -445,13 +476,13 @@ export const CoreFilterCmpt = { /** * */ - handlerRemoveCustomFilter: function(event) { + handlerRemoveCustomFilter(event) { let filterId = event.currentTarget.getAttribute("href").substring(1); if (filterId === this.selectedFilter) this.selectedFilter = null; // this.startFetchCmpt( - CoreFilterAPIs.removeCustomFilter, + this.$fhcApi.factory.filter.removeCustomFilter, { filterId: filterId }, @@ -488,12 +519,42 @@ export const CoreFilterCmpt = { applyFilterConfig(filterFields) { this.selectedFilter = null; this.startFetchCmpt( - CoreFilterAPIs.applyFilterFields, + this.$fhcApi.factory.filter.applyFilterFields, { filterFields }, this.getFilter ); + }, + // TODO check ob im core so bleiben soll + // 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 = []; + + // if child is not included in children array, append the child + if (!parent._children.includes(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() { @@ -522,7 +583,7 @@ export const CoreFilterCmpt = {
-
@@ -531,7 +592,7 @@ export const CoreFilterCmpt = {
-
+
- Mit {{selectedData.length}} ausgewählten: + Mit {{selectedData.length}} ausgewählten: +
[ {{ filterName }} ] @@ -583,4 +645,3 @@ export const CoreFilterCmpt = {
` }; - diff --git a/public/js/plugin/FhcApi.js b/public/js/plugin/FhcApi.js index bacd27d43..4bbf4d4dc 100644 --- a/public/js/plugin/FhcApi.js +++ b/public/js/plugin/FhcApi.js @@ -1,5 +1,5 @@ import FhcAlert from './FhcAlert.js'; -import FhcApiFactory from '../apps/api/fhcapifactory.js'; +import FhcApiFactory from '../api/fhcapifactory.js'; export default { @@ -58,7 +58,7 @@ export default { if (config.data instanceof FormData) return config; - + if (!Object.values(config.data).every(item => { if (item instanceof FileList) return false; @@ -96,18 +96,18 @@ export default { || response.config?.errorHandling === false || response.config?.errorHandling == 'fail') return _clean_return_value(response); - + // NOTE(chris): loop through errors if (response.data.errors) response.data.errors = response.data.errors.filter( - err => (response.config[err.type + 'ErrorHandler'] || app.config.globalProperties.$fhcApi._defaultErrorHandlers[err.type])(err, response.config.form) + err => (response.config[err.type + 'ErrorHandler'] || app.config.globalProperties.$fhcApi._defaultErrorHandlers[err.type])(err, response.config) ); return _clean_return_value(response); }, error => { if (error.code == 'ERR_CANCELED') - return new Promise(() => {}); - + return Promise.reject({...{handled: true}, ...error}); + if (error.config?.errorHandling == 'off' || error.config?.errorHandling === false || error.config?.errorHandling == 'success') @@ -116,23 +116,23 @@ export default { if (error.response) { if (error.response.status == 404) { app.config.globalProperties.$fhcAlert.alertDefault('error', error.message, error.request.responseURL, true); - return new Promise(() => {}); + return Promise.reject({...{handled: true}, ...error}); } - + // NOTE(chris): loop through errors error.response.data.errors = error.response.data.errors.filter( - err => (error.config[err.type + 'ErrorHandler'] || app.config.globalProperties.$fhcApi._defaultErrorHandlers[err.type])(err, error.config.form) + err => (error.config[err.type + 'ErrorHandler'] || app.config.globalProperties.$fhcApi._defaultErrorHandlers[err.type])(err, error.config) ); if (!error.response.data.errors.length) - return new Promise(() => {}); + return Promise.reject({...{handled: true}, ...error}); } else if (error.request) { app.config.globalProperties.$fhcAlert.alertDefault('error', error.message, error.request.responseURL); - return new Promise(() => {}); + return Promise.reject({...{handled: true}, ...error}); } else { app.config.globalProperties.$fhcAlert.alertError(error.message); - return new Promise(() => {}); + return Promise.reject({...{handled: true}, ...error}); } - + return Promise.reject(error); }); @@ -152,30 +152,47 @@ export default { return fhcApiAxios.post(uri, data, config); }, _defaultErrorHandlers: { - validation(error, form) { + validation(error, config) { const $fhcAlert = app.config.globalProperties.$fhcAlert; - if (form) { - form.clearValidation(); - form.setFeedback(false, error.messages); + if (config?.form) { + config.form.clearValidation(); + config.form.setFeedback(false, error.messages); return false; } if (Array.isArray(error.messages)) { error.messages.forEach($fhcAlert.alertError); return false; } else if (typeof error.messages == 'object') { - Object.entries(error.messages).forEach( - ([key, value]) => $fhcAlert.alertDefault('error', key, value, true) - ); + if (config?.errorHeader) + Object.values(error.messages).forEach( + value => $fhcAlert.alertDefault( + 'error', + Array.isArray(config.errorHeader) ? app.config.globalProperties.$p.t.apply(null, config.errorHeader) : config.errorHeader, + value, + true + ) + ); + else + Object.entries(error.messages).forEach( + ([key, value]) => $fhcAlert.alertDefault('error', key, value, true) + ); return false; } return true; }, - general(error, form) { + general(error, config) { const $fhcAlert = app.config.globalProperties.$fhcAlert; - if (form) - form.setFeedback(false, error.message); + if (config?.form) + config.form.setFeedback(false, error.message); + else if (config?.errorHeader) + $fhcAlert.alertDefault( + 'error', + Array.isArray(config.errorHeader) ? app.config.globalProperties.$p.t.apply(null, config.errorHeader) : config.errorHeader, + error.message, + true + ); else $fhcAlert.alertError(error.message); }, @@ -250,6 +267,23 @@ export default { message += 'Line Number: ' + error.line + '\n'; $fhcAlert.alertSystemError(message); + }, + auth(error, config) { + const $fhcAlert = app.config.globalProperties.$fhcAlert; + + var message = ''; + message += 'Controller name: ' + error.controller + '\n'; + message += 'Method name: ' + error.method + '\n'; + message += 'Required permissions: ' + error.required_permissions; + if (config?.errorHeader) + $fhcAlert.alertDefault( + 'error', + Array.isArray(config.errorHeader) ? app.config.globalProperties.$p.t.apply(null, config.errorHeader) : config.errorHeader, + error.message, + true + ); + else + $fhcAlert.alertDefault('error', error.message, message); } } }; @@ -276,7 +310,9 @@ export default { } } - app.config.globalProperties.$fhcApi.factory = new FhcApiFactoryWrapper(FhcApiFactory); + const mergedFhcApiFactory = options?.factory ? {...FhcApiFactory, ...options.factory} : FhcApiFactory; + + app.config.globalProperties.$fhcApi.factory = new FhcApiFactoryWrapper(mergedFhcApiFactory); } }; \ No newline at end of file diff --git a/system/dbupdate_3.4.php b/system/dbupdate_3.4.php index d61c34f7a..687ecde29 100644 --- a/system/dbupdate_3.4.php +++ b/system/dbupdate_3.4.php @@ -437,37 +437,37 @@ echo '

Gegenpruefung!

'; $error=false; $sql_query="SELECT schemaname,tablename FROM pg_catalog.pg_tables WHERE schemaname != 'pg_catalog' AND schemaname != 'information_schema' AND schemaname != 'sync' AND schemaname != 'addon' AND schemaname != 'reports' AND schemaname != 'extension';"; if (!$result=@$db->db_query($sql_query)) - echo '
'.$db->db_last_error().'
'; - else - while ($row=$db->db_fetch_object($result)) + echo '
'.$db->db_last_error().'
'; +else + while ($row=$db->db_fetch_object($result)) + { + $fulltablename=$row->schemaname.'.'.$row->tablename; + if (!isset($tabellen[$fulltablename])) { - $fulltablename=$row->schemaname.'.'.$row->tablename; - if (!isset($tabellen[$fulltablename])) - { - echo 'Tabelle '.$fulltablename.' existiert in der DB, aber nicht in diesem Skript!
'; - $error=true; - } - else - if (!$result_fields=@$db->db_query("SELECT * FROM $fulltablename LIMIT 1;")) - echo '
'.$db->db_last_error().'
'; - else - for ($i=0; $i<$db->db_num_fields($result_fields); $i++) - { - $found=false; - $fieldnameDB=$db->db_field_name($result_fields,$i); - foreach ($tabellen[$fulltablename] AS $fieldnameARRAY) - if ($fieldnameDB==$fieldnameARRAY) - { - $found=true; - break; - } - if (!$found) - { - echo 'Attribut '.$fulltablename.'.'.$fieldnameDB.' existiert in der DB, aber nicht in diesem Skript!
'; - $error=true; - } - } + echo 'Tabelle '.$fulltablename.' existiert in der DB, aber nicht in diesem Skript!
'; + $error=true; } + else + if (!$result_fields=@$db->db_query("SELECT * FROM $fulltablename LIMIT 1;")) + echo '
'.$db->db_last_error().'
'; + else + for ($i=0; $i<$db->db_num_fields($result_fields); $i++) + { + $found=false; + $fieldnameDB=$db->db_field_name($result_fields,$i); + foreach ($tabellen[$fulltablename] AS $fieldnameARRAY) + if ($fieldnameDB==$fieldnameARRAY) + { + $found=true; + break; + } + if (!$found) + { + echo 'Attribut '.$fulltablename.'.'.$fieldnameDB.' existiert in der DB, aber nicht in diesem Skript!
'; + $error=true; + } + } + } if($error==false) echo '
Gegenpruefung fehlerfrei'; -?> +?> \ No newline at end of file