diff options
| author | Aaron Bohy <aab@odoo.com> | 2019-03-18 14:51:04 +0000 |
|---|---|---|
| committer | Aaron Bohy <aab@odoo.com> | 2019-04-02 11:55:57 +0000 |
| commit | 9fbb4fb44ff92cdee53454ab328c10ae66a11aa0 (patch) | |
| tree | 5fd611cbf41a582951250558ff1055ffe9fba9fe /addons/web/static/src/js | |
| parent | a75fa7e377829ac22f85eab3bfefd79705458236 (diff) | |
[IMP] web: editable list: table-layout: fixed
This rev. changes the layout of *editable* list views to a fixed
layout. This means that we are now responsible of the width of
each column. To do that, we associate with each field type a
factor, and the higher the factor is, the larger the column will
be (w.r.t. the others). This default value can be overriden in the
arch.
The fixed layout allows to remove the absolute positionning of
widgets inside editable lists (done in the next commit).
Part of task 1915702
Co-authored-by: Martin Geubelle <mge@odoo.com>
Diffstat (limited to 'addons/web/static/src/js')
4 files changed, 97 insertions, 7 deletions
diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 4940839e612..1c5c19ebcf8 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -444,7 +444,6 @@ var FieldChar = InputField.extend(TranslatableFieldMixin, { }, }); - var LinkButton = AbstractField.extend({ events: _.extend({}, AbstractField.prototype.events, { 'click': '_onClick' @@ -483,7 +482,6 @@ var LinkButton = AbstractField.extend({ event.stopPropagation(); window.open(this.value, '_blank'); }, - }); var FieldDate = InputField.extend({ @@ -1164,6 +1162,7 @@ var FieldText = InputField.extend(TranslatableFieldMixin, { */ var HandleWidget = AbstractField.extend({ className: 'o_row_handle fa fa-arrows ui-sortable-handle', + widthFactor: 0, tagName: 'span', description: "", supportedFieldTypes: ['integer'], diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index 7be77cedca0..0f247ba3a8d 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -766,6 +766,7 @@ var FieldMany2One = AbstractField.extend({ }); var ListFieldMany2One = FieldMany2One.extend({ + //-------------------------------------------------------------------------- // Private //-------------------------------------------------------------------------- diff --git a/addons/web/static/src/js/views/list/list_editable_renderer.js b/addons/web/static/src/js/views/list/list_editable_renderer.js index 9e31a188922..687f046b7e6 100644 --- a/addons/web/static/src/js/views/list/list_editable_renderer.js +++ b/addons/web/static/src/js/views/list/list_editable_renderer.js @@ -447,6 +447,41 @@ ListRenderer.include({ } }, /** + * Returns the relative width according to the widget or the field type. + * @see _renderHeader + * + * @param {Object} column a `field` arch node + */ + _getColumnWidthFactor: function (column) { + if (column.attrs.width) { + // the width attribute has precedence on the width factor + return 0; + } + var fieldType = this.state.fields[column.attrs.name].type; + var widget = this.state.fieldsInfo.list[column.attrs.name].Widget.prototype; + if ('widthFactor' in widget) { + return widget.widthFactor; + } + switch (fieldType) { + case 'binary': return 1; + case 'boolean': return 0.4; + case 'char': return 1; + case 'date': return 1; + case 'datetime': return 1.5; + case 'float': return 1; + case 'html': return 3; + case 'integer': return 0.8; + case 'many2many': return 2.2; + case 'many2one': return 1.5; + case 'monetary': return 1.2; + case 'one2many': return 2.2; + case 'reference': return 1.5; + case 'selection': return 1.5; + case 'text': return 3; + default: return 1; + } + }, + /** * * @returns {integer} */ @@ -655,6 +690,30 @@ ListRenderer.include({ }); }, /** + * Overridden to set weights on columns for the fixed layout. + * + * @override + * @private + */ + _processColumns: function () { + this._super.apply(this, arguments); + + if (this.editable) { + var self = this; + this.columns.forEach(function (column) { + if (column.attrs.width_factor) { + column.attrs.widthFactor = parseFloat(column.attrs.width_factor, 10); + } else { + if (column.tag === 'field') { + column.attrs.widthFactor = self._getColumnWidthFactor(column); + } else { + column.attrs.widthFactor = 1; + } + } + }); + } + }, + /** * @override * @returns {Promise} */ @@ -709,6 +768,34 @@ ListRenderer.include({ return $body; }, /** + * Override to optionally add a th in the header for the remove icon column. + * + * @override + * @private + */ + _renderHeader: function () { + var $thead = this._super.apply(this, arguments); + + if (this.editable) { + var totalWidth = this.columns.reduce(function (acc, column) { + return acc + column.attrs.widthFactor; + }, 0); + this.columns.forEach(function (column) { + var $cell = $thead.find('th[data-name=' + column.attrs.name + ']'); + if (column.attrs.width) { + $cell.css('width', column.attrs.width); + } else if (column.attrs.widthFactor) { + $cell.css('width', (column.attrs.widthFactor / totalWidth * 100) + '%'); + } + }); + } + + if (this.addTrashIcon) { + $thead.find('tr').append($('<th>', {class: 'o_list_record_remove_header'})); + } + return $thead; + }, + /** * Editable rows are possibly extended with a trash icon on their right, to * allow deleting the corresponding record. * For many2many editable lists, the trash bin is replaced by X. diff --git a/addons/web/static/src/js/views/list/list_renderer.js b/addons/web/static/src/js/views/list/list_renderer.js index 670f311c195..7a46e3b3cf2 100644 --- a/addons/web/static/src/js/views/list/list_renderer.js +++ b/addons/web/static/src/js/views/list/list_renderer.js @@ -54,7 +54,6 @@ var ListRenderer = BasicRenderer.extend({ // This attribute lets us know if there is a handle widget on a field, // and on which field it is set. this.handleField = null; - this._processColumns(params.columnInvisibleFields || {}); this.rowDecorations = _.chain(this.arch.attrs) .pick(function (value, key) { return DECORATIONS.indexOf(key) >= 0; @@ -67,6 +66,7 @@ var ListRenderer = BasicRenderer.extend({ this.editable = params.editable; this.isGrouped = this.state.groupedBy.length > 0; this.groupbys = params.groupbys; + this._processColumns(params.columnInvisibleFields || {}); }, //-------------------------------------------------------------------------- @@ -188,7 +188,7 @@ var ListRenderer = BasicRenderer.extend({ */ _processColumns: function (columnInvisibleFields) { var self = this; - self.handleField = null; + this.handleField = null; this.columns = _.reject(this.arch.children, function (c) { if (c.tag === 'control' || c.tag === 'groupby') { return true; @@ -313,7 +313,7 @@ var ListRenderer = BasicRenderer.extend({ isPassword: 'password' in node.attrs, }); this._handleAttributes($td, node); - return $td.html(formattedValue); + return $td.html(formattedValue).attr('title', formattedValue); }, /** * Renders the button element associated to the given node and record. @@ -641,13 +641,14 @@ var ListRenderer = BasicRenderer.extend({ } var description; if (node.attrs.widget) { + $th.addClass(' o_' + node.attrs.widget + '_cell'); description = this.state.fieldsInfo.list[name].Widget.prototype.description; } if (description === undefined) { description = node.attrs.string || field.string; } $th.text(description) - .data('name', name) + .attr('data-name', name) .toggleClass('o-sort-down', isNodeSorted ? !order[0].asc : false) .toggleClass('o-sort-up', isNodeSorted ? order[0].asc : false) .addClass(field.sortable && 'o_column_sortable'); @@ -669,6 +670,8 @@ var ListRenderer = BasicRenderer.extend({ attrs: node.attrs, }; this._addFieldTooltip(fieldDescr, $th); + } else { + $th.attr('title', description); } return $th; }, @@ -722,7 +725,7 @@ var ListRenderer = BasicRenderer.extend({ if (disableInput) { $content.find("input[type='checkbox']").prop('disabled', disableInput); } - return $('<' + tag + ' width="1">') + return $('<' + tag + '>') .addClass('o_list_record_selector') .append($content); }, |
