From a3e7e7ea4a8210858a4d185717c13a2bac65725a Mon Sep 17 00:00:00 2001 From: Arne Morken Date: Sun, 6 Feb 2022 17:31:35 +0100 Subject: [PATCH] Implemented direction of sorting. --- data/anyTable.php | 15 +++++--- data/plugins/group/groupTable.php | 2 +- view/anyModel.js | 3 +- view/anyView.js | 59 +++++++++++++++++++------------ 4 files changed, 51 insertions(+), 28 deletions(-) diff --git a/data/anyTable.php b/data/anyTable.php index 8535b21..7ca848f 100644 --- a/data/anyTable.php +++ b/data/anyTable.php @@ -104,6 +104,7 @@ * - "idKeyMetaTable": The id key used in the meta table, "event_id" or "user_id". * - "nameKey": The name key used by the client and in the table, e.g. "event_name" or "login_name". * - "orderBy": The field to sort by. e.g. "event_date_start". + * - "orderDir": The direction of the sort, "ASC" or "DESC". * - "metaId": The name of the id foeld in the meta table, e.g. "meta_id" or "umeta_id". * - "fields": An array containing the field names of the table. * - "fieldsMeta": An array containing the name of the meta keys of the meta table. @@ -146,6 +147,7 @@ class anyTable extends dbTable $mFilters = null, $mPermission = null, $mOrderBy = null, + $mOrderDir = "ASC", $mSortFunction = null; protected $mInsertSuccessMsg = "", @@ -228,7 +230,8 @@ private function initProperties($defsOrType) $this->mIdKeyTable = $defsOrType["idKeyTable"]; $this->mIdKeyMetaTable = $defsOrType["idKeyMetaTable"]; $this->mNameKey = $defsOrType["nameKey"]; - $this->mOrderBy = $defsOrType["orderBy"]; + $this->mOrderBy = isset($defsOrType["orderBy"]) ? $defsOrType["orderBy"] : null; + $this->mOrderDir = isset($defsOrType["orderDir"]) ? $defsOrType["orderDir"] : "ASC"; $this->mMetaId = $defsOrType["metaId"]; // Set table fields, meta table fields and user link table fields @@ -795,8 +798,11 @@ protected function dbSearchList(&$data,$skipOwnId=false,$flat=false,$simple=fals return true; // We do not have subusers (user table does not have parent_id field) TODO! Neccessary? // Build and execute the full statement - if (Parameters::get("order")) + if (Parameters::get("order")) { $this->mOrderBy = ltrim(Parameters::get("order")); + if (Parameters::get("dir")) + $this->mOrderDir = ltrim(Parameters::get("dir")); + } $partial_stmt = $this->dbPrepareSearchListStmt($skipOwnId); $limit = $this->findLimit(); $stmt = $partial_stmt.$limit; @@ -999,11 +1005,12 @@ protected function findListWhere($skipOwnId=false) return $where; } // findListWhere - protected function findListOrderBy($sort="ASC") + protected function findListOrderBy() { if (!isset($this->mOrderBy)) return ""; - $ob = "ORDER BY ".$this->getTableName().".".$this->mOrderBy." ".$sort." "; + $dir = $this->mOrderDir ? $this->mOrderDir : ""; + $ob = "ORDER BY ".$this->getTableName().".".$this->mOrderBy." ".$dir." "; return $ob; } // findListOrderBy diff --git a/data/plugins/group/groupTable.php b/data/plugins/group/groupTable.php index 509578e..f20f915 100644 --- a/data/plugins/group/groupTable.php +++ b/data/plugins/group/groupTable.php @@ -125,7 +125,7 @@ protected function initFilters($filters) /////////////////////// Database query fragments //////////////////////////// ///////////////////////////////////////////////////////////////////////////// - protected function findListOrderBy($sort="ASC") + protected function findListOrderBy() { return "ORDER BY ".$this->getTableName().".group_sort_order,". $this->getTableName().".group_type,". diff --git a/view/anyModel.js b/view/anyModel.js index d706375..478a42e 100644 --- a/view/anyModel.js +++ b/view/anyModel.js @@ -1283,7 +1283,8 @@ anyModel.prototype.dbSearchGetURL = function (options) param_str += options.grouping ? "&grouping="+options.grouping : ""; param_str += options.from || options.from==0 ? "&from="+options.from : ""; param_str += options.num ? "&num=" +options.num : ""; - param_str += options.order ? "&order=" +options.order : ""; + param_str += options.order ? "&order="+options.order : ""; + param_str += options.direction ? "&dir=" +options.direction: ""; return this._getDataSourceName() + param_str; }; // dbSearchGetURL diff --git a/view/anyView.js b/view/anyView.js index 4f41ea1..448d70c 100644 --- a/view/anyView.js +++ b/view/anyView.js @@ -61,6 +61,8 @@ * (integer) currentPage: The current page to show. Only applicable for "list" and "select" kinds. * (integer) itemsPerPage: The number of rows to show per page. Only applicable for "list" and "select" kinds. * {string} grouping: How to group data: Empty string for no grouping, "tabs" for using anyViewTabs to group data into tabs. Default: "". + * {string} sortBy: The filter id of the table header that the table should be sorted by. Only valid if isSortable is `true`. Default: "". + * {string} sortDirection: Whether the sorting of tables should be ascending (`ASC`) or descending (`DESC`). Only valid if isSortable is `true`. Default: "`ASC`". * {boolean} refresh: If true, the constructor will call `this.refresh` at the end of initialization. Default: false. * {boolean} uploadDirect: If true, the selected file will be uploaded without the user having to press the "edit" and "update" buttons. Default: true. * @@ -111,6 +113,8 @@ $.widget("any.View", { currentPage: 1, itemsPerPage: 20, grouping: "", + sortBy: "", + sortDirection: "ASC", refresh: false, uploadDirect: true, linkIcons: null, @@ -436,8 +440,10 @@ $.any.View.prototype.refreshLoop = function (parent,data,id,type,kind,edit,pdata throw i18n.error.VIEW_AREA_MISSING; ++this.options.ref_rec; - if (this.options.ref_rec > ANY_MAX_REF_REC) + if (this.options.ref_rec > ANY_MAX_REF_REC) { + this.options.ref_rec = 0; throw i18n.error.TOO_MUCH_RECURSION; + } if (this.must_empty) // Paginator button pressed $("#"+this.options.id).empty(); @@ -936,7 +942,9 @@ $.any.View.prototype.refreshThead = function (thead,data,id,type,kind,edit,id_st let pl = this.options.indent_level * this.options.indent_amount; let pl_str = pl > 0 && filter_id == name_key ? "padding-left:"+pl+"px;" : ""; let style_str = disp_str || pl_str ? "style='"+disp_str+pl_str+"'" : ""; - let th = $(""+filter_key.HEADER+""); + let sort_dir = this.options.sortDirection == "ASC" ? "fas fa-sort-up" : "fas fa-sort-down"; + let sort_arr = this.options.isSortable && this.options.sortBy == filter_id ? " 
" : ""; + let th = $(""+filter_key.HEADER+sort_arr+""); tr.append(th); if (this.options.isSortable) { th.css("cursor","pointer"); @@ -974,29 +982,35 @@ $.any.View.prototype.sortTable = function (event) } let type = event.data.type; let order = event.data.filter_id; + let last_sort_by = this.options.sortBy; + this.options.sortBy = order; + if (this.options.sortBy == last_sort_by) + this.options.sortDirection = this.options.sortDirection == "ASC" ? "DESC" : "ASC"; + let from = null; + let num = null; + let table = $("#"+event.data.table_id); + if (table.length) { + let tfoot = table.find("tfoot"); + if (tfoot.length) { + let pager = tfoot.data("pager"); + if (pager) { + from = pager.options.itemsPerPage *(pager.currentPage() - 1); + num = pager.options.itemsPerPage; + } + } + this.must_empty = $("#"+this.options.id); // Tell refresh loop to empty (to avoid flashing) + } + let mod_opt = { context: this.model, + type: type, + from: from, + num: num, + order: order, + direction: this.options.sortDirection, + }; if (this.model.mode == "remote") { // Remote search, let the database do the search. // Will (normally) call refresh via onModelChange - let from = null; - let num = null; - let table = $("#"+event.data.table_id); - if (table.length) { - let tfoot = table.find("tfoot"); - if (tfoot.length) { - let pager = tfoot.data("pager"); - if (pager) { - from = pager.options.itemsPerPage *(pager.currentPage() - 1); - num = pager.options.itemsPerPage; - } - } - this.must_empty = $("#"+this.options.id); // Tell refresh loop to empty (to avoid flashing) - } - let mod_opt = { context: this.model, - type: type, - from: from, - num: num, - order: order, - }; + this.options.ref_rec = 0; this.model.dbSearch(mod_opt); } // if remote else { @@ -1068,6 +1082,7 @@ $.any.View.prototype.pageNumClicked = function (pager) num: num, }; if (this.model.mode == "remote") { + this.options.ref_rec = 0; this.model.dbSearch(mod_opt); } else {