From aead693675aefb985c5f9e43d8a17b38226ddb68 Mon Sep 17 00:00:00 2001 From: Paolo Date: Mon, 10 Oct 2022 14:38:02 +0200 Subject: [PATCH] - Removed not used methods sortSelectedFields, removeSelectedField and addSelectedField from controllers/components/Filter - Removed not used methods sortSelectedFields, addSelectedField and removeSelectedField from libraries/FilterCmptLib - CSS fixes for FilterComponent and NavigationComponent - Removed not used API calls from public/js/components/filter/API.js - Added second level menu entries to the NavigationComponent - Added new property side-menu to the FilterComponent to render the filters selection via the NavigationComponent or directly from the FilterComponent - FilterComponent: - Column positioning is now managed by tabulator - Splitted the column selection from the filter options - Added the rendering of the filters selection via an optional dropdown - Changed the usability and the look of the filter options - German translation --- application/controllers/components/Filter.php | 56 -- application/libraries/FilterCmptLib.php | 91 +--- public/css/components/FilterComponent.css | 6 +- public/css/components/NavigationComponent.css | 8 + public/js/components/filter/API.js | 48 +- public/js/components/filter/Filter.js | 495 +++++++++++------- public/js/components/navigation/Navigation.js | 11 + 7 files changed, 331 insertions(+), 384 deletions(-) diff --git a/application/controllers/components/Filter.php b/application/controllers/components/Filter.php index 480e98548..ab7e1493e 100644 --- a/application/controllers/components/Filter.php +++ b/application/controllers/components/Filter.php @@ -41,62 +41,6 @@ class Filter extends FHC_Controller $this->outputJsonSuccess($this->filtercmptlib->getSession()); } - /** - * Change the sort of the selected fields of the current filter and - * its data will be written on the output in JSON format - */ - public function sortSelectedFields() - { - $request = $this->getPostJSON(); - - if (property_exists($request, 'selectedFields') - && $this->filtercmptlib->sortSelectedFields($request->selectedFields) == true) - { - $this->outputJsonSuccess('Fields sorted'); - } - else - { - $this->outputJsonError('Wrong parameter'); - } - } - - /** - * Remove a selected field from the current filter and - * its data will be written on the output in JSON format - */ - public function removeSelectedField() - { - $request = $this->getPostJSON(); - - if (property_exists($request, 'selectedField') - && $this->filtercmptlib->removeSelectedField($request->selectedField) == true) - { - $this->outputJsonSuccess('Field removed'); - } - else - { - $this->outputJsonError('Error occurred'); - } - } - - /** - * Add a field to the current filter and its data will be written on the output in JSON format - */ - public function addSelectedField() - { - $request = $this->getPostJSON(); - - if (property_exists($request, 'selectedField') - && $this->filtercmptlib->addSelectedField($request->selectedField) == true) - { - $this->outputJsonSuccess('Field added'); - } - else - { - $this->outputJsonError('Error occurred'); - } - } - /** * Remove an applied filter (SQL where condition) from the current filter */ diff --git a/application/libraries/FilterCmptLib.php b/application/libraries/FilterCmptLib.php index 51fafa90b..97948facf 100644 --- a/application/libraries/FilterCmptLib.php +++ b/application/libraries/FilterCmptLib.php @@ -271,95 +271,6 @@ class FilterCmptLib $this->_setSessionElement(FilterCmptLib::SESSION_TIMEOUT, strtotime('+'.$this->_sessionTimeout.' minutes', time())); } - /** - * Change the sort of the selected fields of the current filter - */ - public function sortSelectedFields($selectedFields) - { - $sortSelectedFields = false; - - // Checks the parameter selectedFields - if (isset($selectedFields) && is_array($selectedFields) && count($selectedFields) > 0) - { - // Retrieves all the used fields by the current filter - $fields = $this->_getSessionElement(self::SESSION_FIELDS); - - // Checks that the given selected fields are present in all the used fields by the current filter - if (!array_diff($selectedFields, $fields)) - { - $this->_setSessionElement(self::SESSION_SELECTED_FIELDS, $selectedFields); // write changes into the session - - $sortSelectedFields = true; - } - } - - return $sortSelectedFields; - } - - /** - * Add a field to the current filter - */ - public function addSelectedField($selectedField) - { - $removeSelectedField = false; - - // Checks the parameter selectedField - if (!isEmptyString($selectedField)) - { - // Retrieves all the used fields by the current filter - $fields = $this->_getSessionElement(self::SESSION_FIELDS); - // Retrieves the selected fields by the current filter - $selectedFields = $this->_getSessionElement(self::SESSION_SELECTED_FIELDS); - - // Checks that the given selected field is present in the list of all the used fields by the current filter - if (in_array($selectedField, $fields)) - { - array_push($selectedFields, $selectedField); // place the new filed at the end of the selected fields list - - $this->_setSessionElement(self::SESSION_SELECTED_FIELDS, $selectedFields); // write changes into the session - - $removeSelectedField = true; - } - } - - return $removeSelectedField; - } - - /** - * Remove a selected field from the current filter - */ - public function removeSelectedField($selectedField) - { - $removeSelectedField = false; - - // Checks the parameter selectedField - if (!isEmptyString($selectedField)) - { - // Retrieves all the used fields by the current filter - $fields = $this->_getSessionElement(self::SESSION_FIELDS); - // Retrieves the selected fields by the current filter - $selectedFields = $this->_getSessionElement(self::SESSION_SELECTED_FIELDS); - - // Checks that the given selected field is present in the list of all the used fields by the current filter - if (in_array($selectedField, $fields)) - { - // If the selected field is present in the list of the selected fields by the current filter - $pos = array_search($selectedField, $selectedFields); - if ($pos !== false) - { - // Then remove it and shift the rest of elements by one if needed - array_splice($selectedFields, $pos, 1); - } - - $this->_setSessionElement(self::SESSION_SELECTED_FIELDS, $selectedFields); // write changes into the session - - $removeSelectedField = true; - } - } - - return $removeSelectedField; - } - /** * Add a filter (SQL where clause) to be applied to the current filter */ @@ -665,7 +576,7 @@ class FilterCmptLib } else // otherwise { - $menuEntry->subscriptDescription = 'Remove'; + $menuEntry->subscriptDescription = '(Remove)'; $menuEntry->subscriptLinkClass = 'remove-custom-filter'; $menuEntry->subscriptLinkValue = $filter->{self::FILTER_ID}; diff --git a/public/css/components/FilterComponent.css b/public/css/components/FilterComponent.css index 345b26148..cd0b33a48 100644 --- a/public/css/components/FilterComponent.css +++ b/public/css/components/FilterComponent.css @@ -15,13 +15,13 @@ padding: 10px; } -.filter-dnd-area { +.filter-fields-area { height: 50px; padding: 3px; margin-bottom: 10px; } -.filter-dnd-object { +.filter-fields-field { height: 100%; margin-left: 7px; padding: 11px; @@ -32,7 +32,7 @@ border-width: 1px; border-radius: 7px; font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; - cursor: move; + cursor: pointer; } .filter-filter-fields { diff --git a/public/css/components/NavigationComponent.css b/public/css/components/NavigationComponent.css index 3e2273b67..2d64d9cdc 100644 --- a/public/css/components/NavigationComponent.css +++ b/public/css/components/NavigationComponent.css @@ -55,6 +55,14 @@ border-bottom: none !important; } +.left-side-menu-second-level span { + display: inline-flex; +} + +.remove-custom-filter { + font-size: 10px !important; +} + .left-side-menu-link-entry { font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; font-size: 14px; diff --git a/public/js/components/filter/API.js b/public/js/components/filter/API.js index 9c208a08c..ff09c452d 100644 --- a/public/js/components/filter/API.js +++ b/public/js/components/filter/API.js @@ -40,6 +40,22 @@ export const CoreFilterAPIs = { } ); }, + /** + * + */ + removeCustomFilter: function(wsParams) { + return CoreRESTClient.post( + 'components/Filter/removeCustomFilter', + { + filterUniqueId: wsParams.filterUniqueId, + filterType: wsParams.filterType, + filterId: wsParams.filterId + }, + { + timeout: CORE_FILTER_CMPT_TIMEOUT + } + ); + }, /** * */ @@ -72,38 +88,6 @@ export const CoreFilterAPIs = { } ); }, - /** - * - */ - addSelectedField: function(wsParams) { - return CoreRESTClient.post( - 'components/Filter/addSelectedField', - { - filterUniqueId: wsParams.filterUniqueId, - filterType: wsParams.filterType, - selectedField: wsParams.selectedField - }, - { - timeout: CORE_FILTER_CMPT_TIMEOUT - } - ); - }, - /** - * - */ - removeSelectedField: function(wsParams) { - return CoreRESTClient.post( - 'components/Filter/removeSelectedField', - { - filterUniqueId: wsParams.filterUniqueId, - filterType: wsParams.filterType, - selectedField: wsParams.selectedField - }, - { - timeout: CORE_FILTER_CMPT_TIMEOUT - } - ); - }, /** * */ diff --git a/public/js/components/filter/Filter.js b/public/js/components/filter/Filter.js index 5686c514c..478f2448e 100644 --- a/public/js/components/filter/Filter.js +++ b/public/js/components/filter/Filter.js @@ -19,6 +19,10 @@ import {CoreFilterAPIs} from './API.js'; import {CoreRESTClient} from '../../RESTClient.js'; import {CoreFetchCmpt} from '../../components/Fetch.js'; +// +const FILTER_COMPONENT_NEW_FILTER = 'Filter Component New Filter'; +const FILTER_COMPONENT_NEW_FILTER_TYPE = 'Filter Component New Filter Type'; + /** * */ @@ -29,6 +33,10 @@ export const CoreFilterCmpt = { }, props: { title: String, + sideMenu: { + type: Boolean, + default: true + }, filterType: { type: String, required: true @@ -46,13 +54,17 @@ export const CoreFilterCmpt = { selectedFields: null, notSelectedFields: null, filterFields: null, - notFilterFields: null, + columnsAlias: null, + + availableFilters: null, // FetchCmpt binded properties fetchCmptRefresh: false, fetchCmptApiFunction: null, fetchCmptApiFunctionParams: null, - fetchCmptDataFetched: null + fetchCmptDataFetched: null, + + tabulator: null }; }, created: function() { @@ -102,19 +114,23 @@ export const CoreFilterCmpt = { // If the column has to be displayed or not selectedFields.indexOf(columns[i].field) >= 0 ? columns[i].visible = true : columns[i].visible = false; - if( columns[i].hasOwnProperty('resizable') ) { - columns[i].visible ? columns[i].resizable = true : columns[i].resizable = false; + if (columns[i].hasOwnProperty('resizable')) + { + columns[i].visible ? columns[i].resizable = true : columns[i].resizable = false; } } } + this.columnsAlias = columns; + // Define a default tabulator options in case it was not provided let tabulatorOptions = { height: 500, layout: "fitColumns", + movableColumns: true, + reactiveData: true, columns: columns, - data: JSON.parse(JSON.stringify(this.dataset)), - reactiveData: true + data: JSON.parse(JSON.stringify(this.dataset)) }; // If it was provided @@ -122,14 +138,15 @@ export const CoreFilterCmpt = { { // Then copy it... tabulatorOptions = this.tabulatorOptions; - // ...and overwrite the properties data, reactiveData and columns + // ...and overwrite the properties data, reactiveData, movableColumns and columns tabulatorOptions.data = JSON.parse(JSON.stringify(this.dataset)); - tabulatorOptions.reactiveData = true; tabulatorOptions.columns = columns; + tabulatorOptions.reactiveData = true; + tabulatorOptions.movableColumns = true; } // Start the tabulator with the buid options - let tabulator = new Tabulator( + this.tabulator = new Tabulator( "#filterTableDataset", tabulatorOptions ); @@ -140,7 +157,7 @@ export const CoreFilterCmpt = { // Attach all the provided event handlers to the started tabulator for (let i = 0; i < this.tabulatorEvents.length; i++) { - tabulator.on(this.tabulatorEvents[i].event, this.tabulatorEvents[i].handler); + this.tabulator.on(this.tabulatorEvents[i].event, this.tabulatorEvents[i].handler); } } }, @@ -166,12 +183,11 @@ export const CoreFilterCmpt = { this.fields = data.fields; this.selectedFields = data.selectedFields; this.notSelectedFields = this.fields.filter(x => this.selectedFields.indexOf(x) === -1); - this.filterFields = []; - let tmpFilterFields = []; + 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) { @@ -179,14 +195,20 @@ export const CoreFilterCmpt = { filter.type = data.datasetMetadata[i].type; this.filterFields.push(filter); - tmpFilterFields.push(filter.name); break; } } } - this.notFilterFields = this.fields.filter(x => tmpFilterFields.indexOf(x) === -1); - this.setSideMenu(data); + // 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); + } } else { @@ -224,11 +246,17 @@ export const CoreFilterCmpt = { filtersArray[filtersArray.length] = { link: link + personalFilters[filtersCount].filter_id, description: personalFilters[filtersCount].desc, + subscriptDescription: personalFilters[filtersCount].subscriptDescription, + subscriptLinkClass: personalFilters[filtersCount].subscriptLinkClass, + subscriptLinkValue: personalFilters[filtersCount].subscriptLinkValue, sort: filtersCount, - onClickCall: this.handlerGetFilterById + onClickCall: this.handlerGetFilterById, + onClickSubscriptCall: this.handlerRemoveCustomFilter }; } + this.availableFilters = filtersArray; + this.$emit( 'nwNewEntry', { @@ -239,6 +267,40 @@ export const CoreFilterCmpt = { } ); }, + /** + * Set the drop down menu + */ + setDropDownMenu: function(data) { + let filters = data.sideMenu.filters; + let personalFilters = data.sideMenu.personalFilters; + let filtersArray = []; + + for (let filtersCount = 0; filtersCount < filters.length; filtersCount++) + { + let link = filters[filtersCount].link; + + if (link == null) link = '#'; + + filtersArray[filtersArray.length] = { + option: filters[filtersCount].filter_id, + description: filters[filtersCount].desc + }; + } + + for (let filtersCount = 0; filtersCount < personalFilters.length; filtersCount++) + { + let link = personalFilters[filtersCount].link; + + if (link == null) link = '#'; + + filtersArray[filtersArray.length] = { + option: personalFilters[filtersCount].filter_id, + description: personalFilters[filtersCount].desc + }; + } + + this.availableFilters = filtersArray; + }, /** * Used to start/refresh the FetchCmpt */ @@ -278,6 +340,19 @@ export const CoreFilterCmpt = { this.getFilter ); }, + /** + * + */ + handlerRemoveCustomFilter: function(event) { + // + this.startFetchCmpt( + CoreFilterAPIs.removeCustomFilter, + { + filterId: event.currentTarget.getAttribute("href").substring(1) + }, + this.getFilter + ); + }, /** * */ @@ -294,7 +369,11 @@ export const CoreFilterCmpt = { let filterColumn = filterFieldDivRows[i].children[j]; let filterColumnElement = filterColumn.children[0]; - if (filterColumnElement.name != null) + // If the first column then search for the fields dropdown + if (j == 0) filterColumnElement = filterColumnElement.querySelector('select[name=fieldName]'); + + // If the filter name is _not_ null and it is _not_ a new filter + if (filterColumnElement.name != null && filterColumnElement.name != FILTER_COMPONENT_NEW_FILTER) { // Condition if (filterColumnElement.name == 'condition' && filterColumnElement.value == "") @@ -302,6 +381,7 @@ export const CoreFilterCmpt = { alert("Please fill all the filter options"); return; } + // Name if (filterColumnElement.name == 'fieldName') { @@ -340,41 +420,66 @@ export const CoreFilterCmpt = { /** * */ - handlerAddFilterField: function(event) { - // - this.startFetchCmpt( - CoreFilterAPIs.addFilterField, + handlerChangeFilterField: function(oldValue, newValue) { + + // If an old filter has been changed + if (oldValue != "") + { + for (let i = 0; i < this.filterFields.length; i++) { - filterField: event.currentTarget.value - }, - this.getFilter - ); + if (this.filterFields[i].name == oldValue) + { + this.filterFields.splice(i, 1); + break; + } + } + } + + // Then add the new filter + for (let i = 0; i < this.datasetMetadata.length; i++) + { + if (this.datasetMetadata[i].name == newValue) + { + let filter = { + name: this.datasetMetadata[i].name, + type: this.datasetMetadata[i].type + }; + + this.filterFields.push(filter); + break; + } + } }, /** * */ - handlerAddSelectedField: function(event) { - // - this.startFetchCmpt( - CoreFilterAPIs.addSelectedField, - { - selectedField: event.currentTarget.value - }, - this.getFilter - ); + handlerAddNewFilter: function(event) { + // Adds a new empty filter + this.filterFields.push({ + name: FILTER_COMPONENT_NEW_FILTER, + type: FILTER_COMPONENT_NEW_FILTER_TYPE + }); }, - /** + /* * */ - handlerRemoveSelectedField: function(event) { - // - this.startFetchCmpt( - CoreFilterAPIs.removeSelectedField, - { - selectedField: event.currentTarget.getAttribute('field-to-remove') - }, - this.getFilter - ); + handlerToggleSelectedField: function(event) { + + // If it is a selected field + if (this.selectedFields.indexOf(event.target.innerText) != -1) + { + // then hide it + this.tabulator.hideColumn(event.target.innerText); + // and remove it from the this.selectedFields property + this.selectedFields.splice(this.selectedFields.indexOf(event.target.innerText), 1); + } + else // otherwise + { + // show it + this.tabulator.showColumn(event.target.innerText); + // and add it to the this.selectedFields property + this.selectedFields.push(event.target.innerText); + } }, /** * @@ -393,51 +498,30 @@ export const CoreFilterCmpt = { * */ handlerGetFilterById: function(event) { - // + + let filterId = null; + + // Get the attribute href if side menu is rendered + let attr = event.currentTarget.getAttribute("href"); + + // Otherwise get the value of the drop down menu + if (attr == null) + { + filterId = event.currentTarget.value; + } + else + { + filterId = attr.substring(1); + } + + // Ajax call this.startFetchCmpt( CoreFilterAPIs.getFilterById, { - filterId: event.currentTarget.getAttribute("href").substring(1) + filterId: filterId }, this.render ); - }, - handlerDragOver: function(event) { - let draggedFieldToDisplay = event.currentTarget; - let fieldsToDisplayDivs = document.getElementsByClassName('filter-dnd-object'); - let filterFilterOptions = document.getElementsByClassName('filter-filter-options')[0]; - - // For each draggable element - for (let i = 0; i < fieldsToDisplayDivs.length; i++) - { - let fieldToDisplayDiv = fieldsToDisplayDivs[i]; // - - // If the dragged element is not the same element in the loop - if (draggedFieldToDisplay != fieldToDisplayDiv) - { - fieldToDisplayDiv.classList.remove("selection-after"); - fieldToDisplayDiv.classList.remove("selection-before"); - - let fieldToDisplayDivCenter = (filterFilterOptions.offsetLeft + fieldToDisplayDiv.offsetLeft + fieldToDisplayDiv.offsetWidth) / 2; - - if (event.pageX > filterFilterOptions.offsetLeft + fieldToDisplayDiv.offsetLeft - && event.pageX < filterFilterOptions.offsetLeft + fieldToDisplayDiv.offsetLeft + fieldToDisplayDiv.offsetWidth) - { - if (event.pageX > fieldToDisplayDivCenter) - { - fieldToDisplayDiv.classList.add("selection-after"); - fieldToDisplayDiv.classList.remove("selection-before"); - } - else if (event.pageX < fieldToDisplayDivCenter) - { - fieldToDisplayDiv.classList.add("selection-before"); - fieldToDisplayDiv.classList.remove("selection-after"); - } - } - } - } - }, - handlerOnDrop: function() { } }, template: ` @@ -469,28 +553,17 @@ export const CoreFilterCmpt = {
-
-