From 8943aae665ea906aa03bc30cada884c571738b7c Mon Sep 17 00:00:00 2001 From: Martin Geubelle Date: Fri, 28 Apr 2017 14:31:21 +0200 Subject: [PATCH] [FIX] web: deal wih `default_order` attribute One could set the attribute `default_order` in the view arch (like 'name,id desc'). The records should then be sorted accordingly. This feature was not implemented in the new views. This attribute should work on both basic views and embedded views (x2many). The former uses the `sort` argument in `search_read` while the latter is sorted client-side. There is however a potential issue with the latter: as the order is done client-side with records received by the server, if there are more records than the limit, the server will send records without any order. The client side order will thus be done on a fraction of the records. --- .../static/src/js/services/data_manager.js | 12 ++++++++ .../web/static/src/js/views/abstract_view.js | 11 ++++++++ .../static/src/js/views/basic/basic_model.js | 3 +- addons/web/static/tests/views/form_tests.js | 28 +++++++++++++++++++ addons/web/static/tests/views/list_tests.js | 25 +++++++++++++++++ 5 files changed, 78 insertions(+), 1 deletion(-) diff --git a/addons/web/static/src/js/services/data_manager.js b/addons/web/static/src/js/services/data_manager.js index 4786515bb15..cf49dd3aaec 100644 --- a/addons/web/static/src/js/services/data_manager.js +++ b/addons/web/static/src/js/services/data_manager.js @@ -304,6 +304,18 @@ return core.Class.extend({ viewType = viewType === 'tree' ? 'list' : viewType; innerFieldsView.type = viewType; attrs.views[viewType] = self._processFieldsView(_.extend({}, innerFieldsView)); + + // default_order is like: + // 'name,id desc' + // but we need it like: + // [{name: 'id', asc: false}, {name: 'name', asc: true}] + var defaultOrder = innerFieldsView.arch.attrs.default_order; + if (defaultOrder) { + attrs.orderedBy = _.map(defaultOrder.split(','), function (order) { + order = order.split(' '); + return {name: order[0], asc: order[1] !== 'desc'}; + }); + } }); delete field.views; } diff --git a/addons/web/static/src/js/views/abstract_view.js b/addons/web/static/src/js/views/abstract_view.js index f4def9f69c8..af3e36ad45b 100644 --- a/addons/web/static/src/js/views/abstract_view.js +++ b/addons/web/static/src/js/views/abstract_view.js @@ -102,6 +102,17 @@ var AbstractView = Class.extend({ if (params.modelName) { this.loadParams.modelName = params.modelName; } + // default_order is like: + // 'name,id desc' + // but we need it like: + // [{name: 'id', asc: false}, {name: 'name', asc: true}] + var defaultOrder = viewInfo.arch.attrs.default_order; + if (defaultOrder) { + this.loadParams.orderedBy = _.map(defaultOrder.split(','), function (order) { + order = order.split(' '); + return {name: order[0], asc: order[1] !== 'desc'}; + }); + } this.userContext = params.userContext; }, diff --git a/addons/web/static/src/js/views/basic/basic_model.js b/addons/web/static/src/js/views/basic/basic_model.js index ef93028eeba..f7026f27129 100644 --- a/addons/web/static/src/js/views/basic/basic_model.js +++ b/addons/web/static/src/js/views/basic/basic_model.js @@ -37,7 +37,7 @@ odoo.define('web.BasicModel', function (require) { * model: {string, * offset: {integer}, * openGroupByDefault: {boolean}, - * orderedBy: {string[]}, + * orderedBy: {Object[]}, * parentID: {string}, * rawContext: {Object}, * relationField: {string}, @@ -1621,6 +1621,7 @@ var BasicModel = AbstractModel.extend({ res_ids: ids, static: true, type: 'list', + orderedBy: fieldInfo.orderedBy, parentID: record.id, rawContext: rawContext, relationField: field.relation_field, diff --git a/addons/web/static/tests/views/form_tests.js b/addons/web/static/tests/views/form_tests.js index b6d416156aa..f09d98d641e 100644 --- a/addons/web/static/tests/views/form_tests.js +++ b/addons/web/static/tests/views/form_tests.js @@ -3990,5 +3990,33 @@ QUnit.module('Views', { form.destroy(); }); + + QUnit.test('default_order on x2many embedded view', function (assert) { + assert.expect(1); + + this.data.partner.records[0].p = [1, 4]; + + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '
' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
', + res_id: 1, + }); + + assert.ok(form.$('.o_form_field_one2many tbody tr:first td:contains(yop)').length, + "record 1 should be first"); + + form.destroy(); + }); }); }); diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js index 50d5fbd7182..beb3b1843b1 100644 --- a/addons/web/static/tests/views/list_tests.js +++ b/addons/web/static/tests/views/list_tests.js @@ -664,6 +664,31 @@ QUnit.module('Views', { list.destroy(); }); + QUnit.test('use default_order', function (assert) { + assert.expect(3); + + var list = createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '', + mockRPC: function (route, args) { + if (route === '/web/dataset/search_read') { + assert.strictEqual(args.sort, 'foo ASC', + "should correctly set the sort attribute"); + } + return this._super.apply(this, arguments); + }, + }); + + assert.ok(list.$('tbody tr:first td:contains(blip)').length, + "record 3 should be first"); + assert.ok(list.$('tbody tr:eq(3) td:contains(yop)').length, + "record 1 should be first"); + + list.destroy(); + }); + QUnit.test('can display button in edit mode', function (assert) { assert.expect(1);