diff --git a/application/libraries/FilterWidgetLib.php b/application/libraries/FilterWidgetLib.php index cdf0cac3c..d9a3428a0 100644 --- a/application/libraries/FilterWidgetLib.php +++ b/application/libraries/FilterWidgetLib.php @@ -203,7 +203,7 @@ class FilterWidgetLib // Loops in the session for all the filter widgets foreach ($filterWidgetsSession as $filterWidget => $filterWidgetData) { - // If this filter widget is not the currrent used filter widget and the it is expired... + // If this filter widget is not the current used filter widget and the it is expired... if ($this->_filterUniqueId != $filterWidget && $filterWidgetData[self::SESSION_TIMEOUT] <= time()) { cleanSessionElement(self::SESSION_NAME, $filterWidget); // ...remove it @@ -232,7 +232,7 @@ class FilterWidgetLib if ($filterId != null && is_numeric($filterId) && $filterId > 0) { $whereParameters = array( - 'filter_id' => $filterId + self::FILTER_ID => $filterId ); } else @@ -279,6 +279,18 @@ class FilterWidgetLib if ($definition == null && $whereParameters != null) { $definition = $this->_ci->FiltersModel->loadWhere($whereParameters); + + // Last chance!!! + if (!hasData($definition)) // If no data have been found until now the tries the most desperate query + { + $this->_ci->FiltersModel->addOrder('filter_id', 'ASC'); // sort on column filter_id to get the oldest + $whereParameters = array( + 'app' => $app, + 'dataset_name' => $datasetName + ); + + $definition = $this->_ci->FiltersModel->loadWhere($whereParameters); + } } return $definition; @@ -712,8 +724,11 @@ class FilterWidgetLib { $this->_ci->load->model('system/Filters_model', 'FiltersModel'); // to remove the filter definitions from DB - // delete it! - $this->_ci->FiltersModel->delete(array('filter_id' => $filterId)); + // Delete it from database + $this->_ci->FiltersModel->delete(array(self::FILTER_ID => $filterId)); + + // Delete it from session + $this->_dropFromSessionFilterWidgetById($filterId); $removeCustomFilter = true; } @@ -735,7 +750,7 @@ class FilterWidgetLib $session = $this->getSession(); // The filter currently stored in session (the one that is currently used) if ($session != null) { - // Loads the Fitlers model + // Loads the Filters model $this->_ci->load->model('system/Filters_model', 'FiltersModel'); // Loads all the filters related to this page (same dataset_name and same app name) @@ -761,7 +776,7 @@ class FilterWidgetLib '%s?%s=%s', site_url($navigationPage), self::FILTER_ID, - $filter->filter_id + $filter->{self::FILTER_ID} ) // link ); @@ -774,7 +789,7 @@ class FilterWidgetLib { $menuEntry['subscriptDescription'] = 'Remove'; $menuEntry['subscriptLinkClass'] = 'remove-custom-filter'; - $menuEntry['subscriptLinkValue'] = $filter->filter_id; + $menuEntry['subscriptLinkValue'] = $filter->{self::FILTER_ID}; $childrenPersonalArray[] = $menuEntry; // adds to personal filters menu array } } @@ -974,5 +989,29 @@ class FilterWidgetLib return $pos; } + + /** + * Remove from the session the given filter widget + */ + private function _dropFromSessionFilterWidgetById($filterId) + { + // Loads the session for all the filter widgets + $filterWidgetsSession = getSession(self::SESSION_NAME); + + // If something is present in session + if ($filterWidgetsSession != null) + { + // Loops in the session for all the filter widgets + foreach ($filterWidgetsSession as $filterWidget => $filterWidgetData) + { + // If this filter widget is not the one that we are looking for + if ($filterWidgetData[self::FILTER_ID] == $filterId) + { + cleanSessionElement(self::SESSION_NAME, $filterWidget); // ...remove it + break; // stop to search + } + } + } + } } diff --git a/application/views/widgets/filter/filterOptions.php b/application/views/widgets/filter/filterOptions.php index 6f1dd3885..38b5be98a 100644 --- a/application/views/widgets/filter/filterOptions.php +++ b/application/views/widgets/filter/filterOptions.php @@ -21,8 +21,6 @@ -
-
diff --git a/application/views/widgets/filter/selectFilters.php b/application/views/widgets/filter/selectFilters.php index 4b98c629c..5c8243e3e 100644 --- a/application/views/widgets/filter/selectFilters.php +++ b/application/views/widgets/filter/selectFilters.php @@ -1,17 +1,28 @@ +
+ +
+
+ + p->t('filter', 'filterHinzufuegen')); ?>: + + + + + + +
+ +
+ +
+ +
+ + + +
+
-
- -
- - p->t('filter', 'filterHinzufuegen')); ?>: - - - - - - - - -
+ diff --git a/public/css/FilterWidget.css b/public/css/FilterWidget.css index d880a4b58..6c33f63b8 100644 --- a/public/css/FilterWidget.css +++ b/public/css/FilterWidget.css @@ -28,7 +28,6 @@ .drag-and-drop-fields-span { border: 1px solid black; border-radius: 7px; - /*margin-left: 3px;*/ margin-right: 6px; margin-bottom: 10px; padding: 5px 10px; @@ -130,7 +129,20 @@ color: green; } -#dragAndDropFieldsArea -{ +#dragAndDropFieldsArea { display: inline-table !important; } + +.margin-left-25 { + margin-left: 25%; +} + +.up-down-border { + border-top-width: 1px; + border-top-color: #ddd; + border-top-style: solid; + border-bottom-width: 1px; + border-bottom-color: #ddd; + border-bottom-style: solid; +} + diff --git a/public/js/AjaxLib.js b/public/js/AjaxLib.js index 283061dad..b08351e9a 100644 --- a/public/js/AjaxLib.js +++ b/public/js/AjaxLib.js @@ -5,7 +5,7 @@ * @author * @copyright Copyright (c) 2016 fhcomplete.org * @license GPLv3 - * @link https://fhcomplete.org + * @link https://fhcomplete.org * @since Version 1.0.0 */ @@ -54,7 +54,7 @@ var FHC_AjaxClient = { * ajaxCallParameters is an object */ ajaxCallGet: function(remoteController, controllerParameters, ajaxCallParameters) { - FHC_AjaxClient._ajaxCall(remoteController, controllerParameters, HTTP_GET_METHOD, ajaxCallParameters); + FHC_AjaxClient._ajaxCall(remoteController, controllerParameters, HTTP_GET_METHOD, ajaxCallParameters); }, /** @@ -63,7 +63,7 @@ var FHC_AjaxClient = { * ajaxCallParameters is an object */ ajaxCallPost: function(remoteController, controllerParameters, ajaxCallParameters) { - FHC_AjaxClient._ajaxCall(remoteController, controllerParameters, HTTP_POST_METHOD, ajaxCallParameters); + FHC_AjaxClient._ajaxCall(remoteController, controllerParameters, HTTP_POST_METHOD, ajaxCallParameters); }, /** @@ -72,13 +72,13 @@ var FHC_AjaxClient = { isSuccess: function(response) { var isSuccess = false; - if (jQuery.type(response) == "object" && response.hasOwnProperty(CODE) && response.hasOwnProperty(RESPONSE)) - { - if (response.error == SUCCESS) - { - isSuccess = true; - } - } + if (jQuery.type(response) == "object" && response.hasOwnProperty(CODE) && response.hasOwnProperty(RESPONSE)) + { + if (response.error == SUCCESS) + { + isSuccess = true; + } + } return isSuccess; }, @@ -96,8 +96,8 @@ var FHC_AjaxClient = { hasData: function(response) { var hasData = false; - if (FHC_AjaxClient.isSuccess(response)) - { + if (FHC_AjaxClient.isSuccess(response)) + { if ((jQuery.type(response.retval) == "object" && !jQuery.isEmptyObject(response.retval)) || (jQuery.isArray(response.retval) && response.retval.length > 0) || (jQuery.type(response.retval) == "string" && response.retval.trim() != "") @@ -105,7 +105,7 @@ var FHC_AjaxClient = { { hasData = true; } - } + } return hasData; }, @@ -116,10 +116,10 @@ var FHC_AjaxClient = { getData: function(response) { var data = null; - if (FHC_AjaxClient.hasData(response)) - { + if (FHC_AjaxClient.hasData(response)) + { data = response.retval; - } + } return data; }, @@ -130,10 +130,10 @@ var FHC_AjaxClient = { getError: function(response) { var error = "Generic error"; - if (jQuery.type(response) == "object" && !jQuery.isEmptyObject(response) && response.hasOwnProperty(RESPONSE)) - { + if (jQuery.type(response) == "object" && !jQuery.isEmptyObject(response) && response.hasOwnProperty(RESPONSE)) + { error = response.retval; - } + } return error; }, @@ -145,9 +145,9 @@ var FHC_AjaxClient = { var code = 1; // Generic error if (jQuery.type(response) == "object" && response.hasOwnProperty(CODE)) - { - code = response.error; - } + { + code = response.error; + } return code; }, @@ -178,20 +178,20 @@ var FHC_AjaxClient = { * Retrives parameters from URL query string (HTTP GET parameters) */ getUrlParameter: function(sParam) { - var sPageURL = decodeURIComponent(window.location.search.substring(1)), - sURLVariables = sPageURL.split("&"), - sParameterName, - i; + var sPageURL = decodeURIComponent(window.location.search.substring(1)), + sURLVariables = sPageURL.split("&"), + sParameterName, + i; - for (var i = 0; i < sURLVariables.length; i++) + for (var i = 0; i < sURLVariables.length; i++) { - sParameterName = sURLVariables[i].split("="); + sParameterName = sURLVariables[i].split("="); - if (sParameterName[0] === sParam) + if (sParameterName[0] === sParam) { - return sParameterName[1]; - } - } + return sParameterName[1]; + } + } }, //------------------------------------------------------------------------------------------------------------------ @@ -259,7 +259,7 @@ var FHC_AjaxClient = { // Call the error callback saved in _errorCallback property // NOTE: this is not referred to FHC_AjaxClient but to the ajax object - this._errorCallback(jqXHR, textStatus, errorThrown); + this._errorCallback(jqXHR, textStatus, errorThrown); }, /** @@ -279,6 +279,14 @@ var FHC_AjaxClient = { } FHC_AjaxClient._hideVeil(); // finally hide the veil + + // If was required a page reload then do it! + if (this._reloadPage === true) + { + // NOTE: to avoid any conflict with other ajaxs calls + // Otherwise some browsers (eg. firefox) can prompt an error + $(document).ajaxStop(function() { location.reload(); }); + } }, /** @@ -336,14 +344,14 @@ var FHC_AjaxClient = { * Instantiate a new object and copy in it the properties from the parameter */ _cpObjProps: function(obj) { - var returnObj = {}; + var returnObj = {}; - for (var prop in obj) - { - returnObj[prop] = obj[prop]; - } + for (var prop in obj) + { + returnObj[prop] = obj[prop]; + } - return returnObj; + return returnObj; }, /** @@ -384,9 +392,9 @@ var FHC_AjaxClient = { * * @param controllerParameters * Example: { - * name1: value, - * name2: value, - * files: $(selector)[0].files --> this is the FileList + * name1: value, + * name2: value, + * files: $(selector)[0].files --> this is the FileList * } * @returns {boolean} * @private @@ -402,10 +410,6 @@ var FHC_AjaxClient = { return true; } } - /* - return Object.values(controllerParameters) - .some((value) => value instanceof FileList === true); - */ }, /** @@ -454,7 +458,7 @@ var FHC_AjaxClient = { */ _checkAndGenerateAjaxParams: function(remoteController, controllerParameters, type, ajaxCallParameters) { - var valid = true; // by default they are ok (we want to trust you, please do not betray it) + var valid = true; // by default they are ok (we want to trust you, please do not betray it) // Returned parameters var ajaxParameters = { @@ -464,28 +468,28 @@ var FHC_AjaxClient = { }; // remoteController must be a NON-empty string - if (typeof remoteController == "string" && remoteController.trim() != "") - { - // Is it possible to generate the URL - if ((url = FHC_AjaxClient._generateRouterURI(remoteController)) != null) - { - ajaxParameters.url = url; - } - else // but it could fail - { - console.error("FHC_JS_DATA_STORAGE_OBJECT is not present"); - valid = false; - } - } + if (typeof remoteController == "string" && remoteController.trim() != "") + { + // Is it possible to generate the URL + if ((url = FHC_AjaxClient._generateRouterURI(remoteController)) != null) + { + ajaxParameters.url = url; + } + else // but it could fail + { + console.error("FHC_JS_DATA_STORAGE_OBJECT is not present"); + valid = false; + } + } else // otherwise is NOT possible to generate the URL { console.error("Invalid remoteController parameter"); - valid = false; + valid = false; } - // controllerParameters must be an object - if (typeof controllerParameters == "object") - { + // controllerParameters must be an object + if (typeof controllerParameters == "object") + { // If controllerParameters contains uploaded file(s) as FileList if (controllerParameters !== null && FHC_AjaxClient._hasFileList(controllerParameters)) { @@ -511,19 +515,18 @@ var FHC_AjaxClient = { // so the variable data is saved also in _data and it will be used later ajaxParameters.data = data; ajaxParameters._data = data; - } + } else { console.error("Invalid controller parameters, must be an object"); valid = false; } - // Checks if ajaxCallParameters is an object - if (typeof ajaxCallParameters == "object") - { + if (typeof ajaxCallParameters == "object") + { // If present, errorCallback must be a function - if (ajaxCallParameters.hasOwnProperty("errorCallback")) + if (ajaxCallParameters.hasOwnProperty("errorCallback")) { if (typeof ajaxCallParameters.errorCallback == "function") { @@ -535,7 +538,7 @@ var FHC_AjaxClient = { console.error("Invalid errorCallback, it must be a function"); valid = false; } - } + } else // if is not given then call the default errorCallback { ajaxParameters._errorCallback = FHC_AjaxClient._defaultErrorCallback; // save as property the callback error @@ -543,8 +546,8 @@ var FHC_AjaxClient = { } // If present, successCallback must be a function - if (ajaxCallParameters.hasOwnProperty("successCallback")) - { + if (ajaxCallParameters.hasOwnProperty("successCallback")) + { if (typeof ajaxCallParameters.successCallback == "function") { ajaxParameters._successCallback = ajaxCallParameters.successCallback; // save as property the callback success @@ -555,11 +558,11 @@ var FHC_AjaxClient = { console.error("Invalid successCallback, it must be a function"); valid = false; } - } + } // If present, completeCallback must be a function - if (ajaxCallParameters.hasOwnProperty("completeCallback")) - { + if (ajaxCallParameters.hasOwnProperty("completeCallback")) + { if (typeof ajaxCallParameters.completeCallback == "function") { ajaxParameters._completeCallback = ajaxCallParameters.completeCallback; // save as property the callback complete @@ -569,7 +572,7 @@ var FHC_AjaxClient = { console.error("Invalid completeCallback, it must be a function"); valid = false; } - } + } // If present, veilTimeout must be a number and cannot be less then 0 or greater then 60000 if (ajaxCallParameters.hasOwnProperty("veilTimeout") && typeof ajaxCallParameters.veilTimeout == "number") @@ -595,6 +598,24 @@ var FHC_AjaxClient = { ajaxParameters.beforeSend = FHC_AjaxClient._showVeil; } + // If present reloadPage has to be a boolean + if (ajaxCallParameters.hasOwnProperty("reloadPage")) + { + if (typeof ajaxCallParameters.reloadPage != "boolean") + { + console.error("Invalid reloadPage parameter, must be a boolean"); + valid = false; + } + else + { + ajaxParameters._reloadPage = ajaxCallParameters.reloadPage; + } + } + else // not present + { + ajaxParameters._reloadPage = false; + } + // Function to call after the ajax call is ended, is it here because it must be always called ajaxParameters.complete = FHC_AjaxClient._onComplete; } @@ -604,7 +625,7 @@ var FHC_AjaxClient = { ajaxParameters = null; } - return ajaxParameters; + return ajaxParameters; }, /** @@ -622,9 +643,10 @@ var FHC_AjaxClient = { var ajaxParameters = FHC_AjaxClient._checkAndGenerateAjaxParams(remoteController, controllerParameters, type, ajaxCallParameters); // Checks the given parameters if they are present and are valid - if (ajaxParameters != null) - { - $.ajax(ajaxParameters); // ajax call - } + if (ajaxParameters != null) + { + $.ajax(ajaxParameters); // ajax call + } } }; + diff --git a/public/js/FilterWidget.js b/public/js/FilterWidget.js index f63c41013..2563a9629 100644 --- a/public/js/FilterWidget.js +++ b/public/js/FilterWidget.js @@ -46,11 +46,12 @@ function sideMenuHook() filterUniqueId: FHC_FilterWidget.getFilterUniqueIdPrefix() }, { + reloadPage: true, successCallback: function(data, textStatus, jqXHR) { if (FHC_AjaxClient.isError(data)) { - console.log(FHC_AjaxClient.getError(data)); + console.error(FHC_AjaxClient.getError(data)); } else { @@ -141,7 +142,7 @@ var FHC_FilterWidget = { if (FHC_AjaxClient.isError(data)) { - console.log(FHC_AjaxClient.getError(data)); + console.error(FHC_AjaxClient.getError(data)); } else { @@ -157,7 +158,7 @@ var FHC_FilterWidget = { if (FHC_AjaxClient.isError(data)) { - console.log(FHC_AjaxClient.getError(data)); + console.error(FHC_AjaxClient.getError(data)); } else { @@ -174,6 +175,7 @@ var FHC_FilterWidget = { $("#addField").html(""); $("#appliedFilters").html(""); $("#addFilter").html(""); + FHC_FilterWidget._toggleApplySaveButtons(false); // If the choosen dataset representation is tablesorter if (FHC_FilterWidget._datasetRepresentation == DATASET_REP_TABLESORTER) @@ -218,7 +220,7 @@ var FHC_FilterWidget = { } else { - console.log(FHC_AjaxClient.getError(data)); + console.error(FHC_AjaxClient.getError(data)); } } } @@ -290,6 +292,8 @@ var FHC_FilterWidget = { $(".remove-selected-field").off("click"); $("#addField").off("change"); $(".applied-filter-operation").off("change"); + $(".applied-filter-condition").off("keyup"); + $(".applied-filter-option").off("change"); $(".remove-applied-filter").off("click"); $("#addFilter").off("change"); $("#applyFilter").off("click"); @@ -314,6 +318,8 @@ var FHC_FilterWidget = { $(".remove-selected-field").click(FHC_FilterWidget._revomeSelectedFieldsEvent); // Click event on the "X" link $("#addField").change(FHC_FilterWidget._addFieldEvent); // Change event on the fields drop-down to add new fields $(".applied-filter-operation").change(FHC_FilterWidget._appliedFiltersOperationsEvent); // Change event on the operation drop-down + $(".applied-filter-condition").keyup(FHC_FilterWidget._appliedFiltersConditionsEvent); // Change event on the conditions fields + $(".applied-filter-option").change(FHC_FilterWidget._appliedFiltersOptionsEvent); // Change event on the operation drop-down $(".remove-applied-filter").click(FHC_FilterWidget._removeAppliedFiltersEvent); // Click event to the "X" button to remove an applied filter $("#addFilter").change(FHC_FilterWidget._addFilterEvent); // Click event on the applied filters drop-down to add a new filter to the dataset $("#applyFilter").click(FHC_FilterWidget._applyFilterEvent); // Click event on the applied filters drop-down to apply filters to the dataset @@ -456,6 +462,22 @@ var FHC_FilterWidget = { $(this).parent().parent().find(".applied-filter-condition").prop("disabled", false); $(this).parent().parent().find(".applied-filter-option").prop("disabled", false); } + + FHC_FilterWidget._toggleApplySaveButtons(true); + }, + + /** + * Event function used by the applied filter conditions + */ + _appliedFiltersConditionsEvent: function(event) { + FHC_FilterWidget._toggleApplySaveButtons(true); + }, + + /** + * Event function used by the applied filter options + */ + _appliedFiltersOptionsEvent: function(event) { + FHC_FilterWidget._toggleApplySaveButtons(true); }, /** @@ -481,7 +503,7 @@ var FHC_FilterWidget = { * Event function used by the apply filter button * The given parameter is used to decide if the page is going to be reloaded */ - _applyFilterEvent: function(reload = true) { + _applyFilterEvent: function() { var appliedFilters = []; var appliedFiltersOperations = []; @@ -506,15 +528,7 @@ var FHC_FilterWidget = { }, { successCallback: function(data, textStatus, jqXHR) { - - if (reload === true) - { - FHC_FilterWidget._failOrReload(data, textStatus, jqXHR); - } - else - { - console.log(FHC_AjaxClient.getError(data)); - } + FHC_FilterWidget._failOrReload(data, textStatus, jqXHR); } } ); @@ -586,9 +600,6 @@ var FHC_FilterWidget = { if ($("#customFilterDescription").val() != "") { - // Apply the filter before saving it, without reloading the page - FHC_FilterWidget._applyFilterEvent(false); - FHC_AjaxClient.ajaxCallPost( "widgets/Filters/saveCustomFilter", { @@ -597,7 +608,12 @@ var FHC_FilterWidget = { }, { successCallback: function(data, textStatus, jqXHR) { - FHC_FilterWidget._failOrReload(data); + + // If an error occurred then log it + if (FHC_AjaxClient.isError(data)) console.error(data); + + // In any case tries to apply the filter + FHC_FilterWidget._applyFilterEvent(); } } ); @@ -1265,6 +1281,14 @@ var FHC_FilterWidget = { { FHC_FilterWidget._hideOptions = data.hideOptions; } + }, + + /** + * Enable/disable the apply and save buttons + */ + _toggleApplySaveButtons(addedNewFilterOption) { + $("#applyFilter").prop("disabled", addedNewFilterOption != true); + $("#saveCustomFilterButton").prop("disabled", addedNewFilterOption === true); } }; @@ -1276,3 +1300,4 @@ $(document).ready(function() { FHC_FilterWidget.display(); }); + diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 005d1a8a4..b7bbaf03a 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -1577,6 +1577,27 @@ $phrases = array( ) ), + array( + 'app' => 'core', + 'category' => 'filter', + 'phrase' => 'filterApply', + 'insertvon' => 'system', + 'phrases' => array( + array( + 'sprache' => 'German', + 'text' => 'Filtern', + 'description' => '', + 'insertvon' => 'system' + ), + array( + 'sprache' => 'English', + 'text' => 'Apply', + 'description' => '', + 'insertvon' => 'system' + ) + ) + ), + array( 'app' => 'core', 'category' => 'filter',