[IMP] web: list: keep columns width when adding records

Mainly, when adding the first record to the list, as this is when
we switch from forcing the column's widths (when there is no data),
to letting the browser optimally divide the available space.

Some other cases had to be handled, like the multi edition.
This commit is contained in:
Aaron Bohy
2019-08-23 06:28:35 +00:00
parent 4393b012a5
commit 1824020cc2
5 changed files with 178 additions and 5 deletions
@@ -1071,6 +1071,7 @@ var FieldX2Many = AbstractField.extend({
this.currentColInvisibleFields = this._evalColumnInvisibleFields();
return this.renderer.updateState(this.value, {
columnInvisibleFields: this.currentColInvisibleFields,
keepWidths: true,
}).then(function () {
self.pager.updateState({ size: self.value.count });
});
@@ -247,7 +247,7 @@ var ListController = BasicController.extend({
});
}).then(function (recordID) {
var state = self.model.get(self.handle);
self.renderer.updateState(state, {})
self.renderer.updateState(state, {keepWidths: true})
.then(function () {
self.renderer.editRecord(recordID);
}).then(self._updatePager.bind(self));
@@ -405,7 +405,7 @@ var ListController = BasicController.extend({
.then(() => {
this._updateButtons('readonly');
const state = this.model.get(this.handle);
this.renderer.updateState(state, {});
this.renderer.updateState(state, {keepWidths: true});
resolve(Object.keys(changes));
})
.guardedCatch(rejectAndDiscard);
@@ -44,6 +44,7 @@ ListRenderer.include({
this._super.apply(this, arguments);
this.editable = params.editable;
this.columnWidths = false;
// if addCreateLine (resp. addCreateLineInGroups) is true, the renderer
// will add a 'Add a line' link at the bottom of the list view (resp.
@@ -491,6 +492,13 @@ ListRenderer.include({
* @override
*/
updateState: function (state, params) {
this.oldColumns = this.columns;
this.columnWidths = false;
if (params.keepWidths) {
this.columnWidths = this.$('thead th').toArray().map(function (th) {
return $(th).outerWidth();
});
}
if (params.noRender) {
// the state changed, but we won't do a re-rendering right now, so
// remove computed modifiers data (as they are obsolete) to force
@@ -537,10 +545,21 @@ ListRenderer.include({
// there is no record -> don't force column's widths w.r.t. their label
return;
}
let restoreWidths = false;
if (this.columnWidths) {
if (this.oldColumns && this.oldColumns.length === this.columns.length) {
for (let i = 0; i < this.oldColumns.length; i++) {
if (this.oldColumns[i] !== this.columns[i]) {
break;
}
restoreWidths = (i === this.oldColumns.length - 1); // columns are as before
}
}
}
var $thead = this.$('thead');
$thead.find('th').each(function () {
var $th = $(this);
$th.css('width', $th.outerWidth() + 'px');
$thead.find('th').each((index, th) => {
var $th = $(th);
$th.css('width', restoreWidths ? this.columnWidths[index] : $th.outerWidth() + 'px');
});
this.$('table').css('table-layout', 'fixed');
},
@@ -8541,6 +8541,71 @@ QUnit.module('fields', {}, function () {
form.destroy();
});
QUnit.test('column widths are kept when adding first record in o2m', async function (assert) {
assert.expect(2);
var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form>' +
'<field name="p">' +
'<tree editable="top">' +
'<field name="date"/>' +
'<field name="foo"/>' +
'</tree>' +
'</field>' +
'</form>',
});
var width = form.$('th[data-name="date"]')[0].offsetWidth;
await testUtils.dom.click(form.$('.o_field_x2many_list_row_add a'));
assert.containsOnce(form, '.o_data_row');
assert.strictEqual(form.$('th[data-name="date"]')[0].offsetWidth, width);
form.destroy();
});
QUnit.test('column widths are kept when editing a record in o2m', async function (assert) {
assert.expect(2);
this.data.partner.records[0].p = [2];
var form = await createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form>' +
'<field name="p">' +
'<tree editable="top">' +
'<field name="date"/>' +
'<field name="foo"/>' +
'</tree>' +
'</field>' +
'</form>',
res_id: 1,
viewOptions: {
mode: 'edit',
},
});
var width = form.$('th[data-name="date"]')[0].offsetWidth;
await testUtils.dom.click(form.$('.o_data_row .o_data_cell:first'));
assert.strictEqual(form.$('th[data-name="date"]')[0].offsetWidth, width);
var longVal = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed blandit, ' +
'justo nec tincidunt feugiat, mi justo suscipit libero, sit amet tempus ipsum ' +
'purus bibendum est.';
await testUtils.fields.editInput(form.$('.o_field_widget[name=foo]'), longVal);
assert.strictEqual(form.$('th[data-name="date"]')[0].offsetWidth, width);
form.destroy();
});
});
});
});
@@ -1517,6 +1517,94 @@ QUnit.module('Views', {
list.destroy();
});
QUnit.test('column widths are kept when adding first record', async function (assert) {
assert.expect(2);
this.data.foo.records = []; // in this scenario, we start with no records
var list = await createView({
View: ListView,
model: 'foo',
data: this.data,
arch: '<tree editable="top">' +
'<field name="datetime"/>' +
'<field name="text"/>' +
'</tree>',
});
var width = list.$('th[data-name="datetime"]')[0].offsetWidth;
await testUtils.dom.click(list.$buttons.find('.o_list_button_add'));
assert.containsOnce(list, '.o_data_row');
assert.strictEqual(list.$('th[data-name="datetime"]')[0].offsetWidth, width);
list.destroy();
});
QUnit.test('column widths are kept when editing a record', async function (assert) {
assert.expect(3);
var list = await createView({
View: ListView,
model: 'foo',
data: this.data,
arch: '<tree editable="bottom">' +
'<field name="datetime"/>' +
'<field name="text"/>' +
'</tree>',
});
var width = list.$('th[data-name="datetime"]')[0].offsetWidth;
await testUtils.dom.click(list.$('.o_data_row:eq(0) .o_data_cell:eq(1)'));
assert.containsOnce(list, '.o_selected_row');
var longVal = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed blandit, ' +
'justo nec tincidunt feugiat, mi justo suscipit libero, sit amet tempus ipsum purus ' +
'bibendum est.';
await testUtils.fields.editInput(list.$('.o_field_widget[name=text]'), longVal);
await testUtils.dom.click(list.$buttons.find('.o_list_button_save'));
assert.containsNone(list, '.o_selected_row');
assert.strictEqual(list.$('th[data-name="datetime"]')[0].offsetWidth, width);
list.destroy();
});
QUnit.test('column widths are kept when editing multiple records', async function (assert) {
assert.expect(4);
var list = await createView({
View: ListView,
model: 'foo',
data: this.data,
arch: '<tree editable="bottom">' +
'<field name="datetime"/>' +
'<field name="text"/>' +
'</tree>',
});
var width = list.$('th[data-name="datetime"]')[0].offsetWidth;
// select two records and edit
await testUtils.dom.click(list.$('.o_data_row:eq(0) .o_list_record_selector input'));
await testUtils.dom.click(list.$('.o_data_row:eq(1) .o_list_record_selector input'));
await testUtils.dom.click(list.$('.o_data_row:eq(0) .o_data_cell:eq(1)'));
assert.containsOnce(list, '.o_selected_row');
var longVal = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed blandit, ' +
'justo nec tincidunt feugiat, mi justo suscipit libero, sit amet tempus ipsum purus ' +
'bibendum est.';
await testUtils.fields.editInput(list.$('.o_field_widget[name=text]'), longVal);
assert.containsOnce(document.body, '.modal');
await testUtils.dom.click($('.modal .btn-primary'));
assert.containsNone(list, '.o_selected_row');
assert.strictEqual(list.$('th[data-name="datetime"]')[0].offsetWidth, width);
list.destroy();
});
QUnit.test('row height should not change when switching mode', async function (assert) {
// Warning: this test is css dependant
assert.expect(3);