From ff691a34b5b25ff2365ac8c0ba451757c50cfbf8 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 4 May 2011 16:05:35 +0200 Subject: [PATCH 1/2] [ADD] sorting support in list views * Fix sorting in DataSet.do_search_read (would not fix ordering of read results, yielding a semi-random order instead of the one returned by search) * Add sort parameter support to ListView.fill() * Improve handling of sort parameter on DataSetSearch - Queue up fields to sort on (most important last) by calling 'dataset.sort(fieldname)' repeatedly - Get back a sort string fit for sending to OpenERP (server) by calling 'dataset.sort()' (without arguments) * Adds sorting on list view by clicking on headers bzr revid: xmo@openerp.com-20110504140535-ydj8zs33lt0dgcwy --- addons/base/controllers/main.py | 16 +++++++++----- addons/base/static/src/js/data.js | 33 +++++++++++++++++++++++++++-- addons/base/static/src/js/list.js | 10 ++++++++- addons/base/static/src/xml/base.xml | 2 +- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index 8faca685300..424313bc6d2 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -346,12 +346,17 @@ class DataSet(openerpweb.Controller): :rtype: list """ Model = request.session.model(model) + ids = Model.search(domain or [], offset or 0, limit or False, sort or False, request.context) + if fields and fields == ['id']: # shortcut read if we only want the ids return map(lambda id: {'id': id}, ids) - return Model.read(ids, fields or False, request.context) + + reads = Model.read(ids, fields or False, request.context) + reads.sort(key=lambda obj: ids.index(obj['id'])) + return reads @openerpweb.jsonrequest def get(self, request, model, ids, fields=False): @@ -556,11 +561,11 @@ class ListView(View): @openerpweb.jsonrequest def fill(self, request, model, id, domain, - offset=0, limit=False): - return self.do_fill(request, model, id, domain, offset, limit) + offset=0, limit=False, sort=None): + return self.do_fill(request, model, id, domain, offset, limit, sort) def do_fill(self, request, model, id, domain, - offset=0, limit=False): + offset=0, limit=False, sort=None): """ Returns all information needed to fill a table: * view with processed ``editable`` flag @@ -580,9 +585,10 @@ class ListView(View): """ view = self.fields_view_get(request, model, id, toolbar=True) + print sort rows = DataSet().do_search_read(request, model, offset=offset, limit=limit, - domain=domain) + domain=domain, sort=sort) eval_context = request.session.evaluation_context( request.context) return { diff --git a/addons/base/static/src/js/data.js b/addons/base/static/src/js/data.js index 6d566f4de0a..c7c129e7fec 100644 --- a/addons/base/static/src/js/data.js +++ b/addons/base/static/src/js/data.js @@ -144,7 +144,7 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({ init: function(session, model) { this._super(session, model); this.domain = []; - this.sort = []; + this._sort = []; this.offset = 0; // subset records[offset:offset+limit] // is it necessary ? @@ -166,7 +166,7 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({ fields: fields, domain: this.domain, context: this.context, - sort: this.sort, + sort: this.sort(), offset: offset, limit: limit }, function (records) { @@ -177,6 +177,35 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({ } callback(records); }); + }, + /** + * Reads or changes sort criteria on the dataset. + * + * If not provided with any argument, serializes the sort criteria to + * an SQL-like form usable by OpenERP's ORM. + * + * If given a field, will set that field as first sorting criteria or, + * if the field is already the first sorting criteria, will reverse it. + * + * @param {String} [field] field to sort on, reverses it (toggle from ASC to DESC) if already the main sort criteria + * @param {Boolean} [force_reverse=false] forces inserting the field as DESC + * @returns {String|undefined} + */ + sort: function (field, force_reverse) { + if (!field) { + return _.map(this._sort, function (criteria) { + if (criteria[0] === '-') { + return criteria.slice(1) + ' DESC'; + } + return criteria; + }).join(', '); + } + + var reverse = force_reverse || (this._sort[0] === field); + this._sort = _.without(this._sort, field, '-' + field); + + this._sort.unshift((reverse ? '-' : '') + field); + return undefined; } }); diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index cc84efa65f2..308b73f8925 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -130,6 +130,13 @@ openerp.base.ListView = openerp.base.Controller.extend( this.$element.find('#oe-list-delete') .hide() .click(this.do_delete_selected); + this.$element.find('thead').delegate('th[data-id]', 'click', function (e) { + e.stopPropagation(); + + self.dataset.sort($(this).data('id')); + + self.do_reload(); + }); var $table = this.$element.find('table'); // Cell events @@ -318,7 +325,8 @@ openerp.base.ListView = openerp.base.Controller.extend( 'model': this.dataset.model, 'id': this.view_id, 'context': this.dataset.context, - 'domain': this.dataset.domain + 'domain': this.dataset.domain, + 'sort': this.dataset.sort && this.dataset.sort() }, this.do_fill_table); }, /** diff --git a/addons/base/static/src/xml/base.xml b/addons/base/static/src/xml/base.xml index ef4cbba46b0..b2b2bd7d2c4 100644 --- a/addons/base/static/src/xml/base.xml +++ b/addons/base/static/src/xml/base.xml @@ -181,7 +181,7 @@ - + From 075902f5c2b0febd70adf5209b4eef2cfb0813b8 Mon Sep 17 00:00:00 2001 From: Xavier Morel Date: Wed, 4 May 2011 16:47:53 +0200 Subject: [PATCH 2/2] [IMP] make sortable columns look sortable (and sorted) a bit bzr revid: xmo@openerp.com-20110504144753-zemygt44re3o8z0m --- addons/base/controllers/main.py | 10 ++++++++++ addons/base/static/src/css/base.css | 5 +++++ addons/base/static/src/js/data.js | 2 +- addons/base/static/src/js/list.js | 3 +++ addons/base/static/src/xml/base.xml | 4 +++- 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/addons/base/controllers/main.py b/addons/base/controllers/main.py index 424313bc6d2..085e48d89e0 100644 --- a/addons/base/controllers/main.py +++ b/addons/base/controllers/main.py @@ -591,6 +591,16 @@ class ListView(View): domain=domain, sort=sort) eval_context = request.session.evaluation_context( request.context) + + if sort: + sort_criteria = sort.split(',')[0].split(' ') + print sort, sort_criteria + view['sorted'] = { + 'field': sort_criteria[0], + 'reversed': sort_criteria[1] == 'DESC' + } + else: + view['sorted'] = {} return { 'view': view, 'records': [ diff --git a/addons/base/static/src/css/base.css b/addons/base/static/src/css/base.css index 1bd004b53f6..43021e32bc6 100644 --- a/addons/base/static/src/css/base.css +++ b/addons/base/static/src/css/base.css @@ -485,6 +485,11 @@ body.openerp { .openerp .oe-listview td, .openerp .oe-listview th { vertical-align: middle; + text-align: left; +} +.openerp .oe-listview th.oe-sortable, +.openerp .oe-listview th.oe-sortable .ui-icon { + cursor: pointer; } .openerp .oe-listview .oe-field-cell { diff --git a/addons/base/static/src/js/data.js b/addons/base/static/src/js/data.js index c7c129e7fec..da0f18001a8 100644 --- a/addons/base/static/src/js/data.js +++ b/addons/base/static/src/js/data.js @@ -197,7 +197,7 @@ openerp.base.DataSetSearch = openerp.base.DataSet.extend({ if (criteria[0] === '-') { return criteria.slice(1) + ' DESC'; } - return criteria; + return criteria + ' ASC'; }).join(', '); } diff --git a/addons/base/static/src/js/list.js b/addons/base/static/src/js/list.js index 308b73f8925..e9061fa7121 100644 --- a/addons/base/static/src/js/list.js +++ b/addons/base/static/src/js/list.js @@ -123,6 +123,8 @@ openerp.base.ListView = openerp.base.Controller.extend( this.visible_columns = _.filter(this.columns, function (column) { return column.invisible !== '1'; }); + + if (!this.fields_view.sorted) { this.fields_view.sorted = {}; } this.$element.html(QWeb.render("ListView", this)); // Head hook @@ -135,6 +137,7 @@ openerp.base.ListView = openerp.base.Controller.extend( self.dataset.sort($(this).data('id')); + // TODO: should only reload content (and set the right column to a sorted display state) self.do_reload(); }); diff --git a/addons/base/static/src/xml/base.xml b/addons/base/static/src/xml/base.xml index b2b2bd7d2c4..bcd8db9444f 100644 --- a/addons/base/static/src/xml/base.xml +++ b/addons/base/static/src/xml/base.xml @@ -181,9 +181,11 @@ - + +