summaryrefslogtreecommitdiff
path: root/addons/web/static/src/js/views
diff options
context:
space:
mode:
authorAaron Bohy <aab@odoo.com>2020-05-26 15:26:27 +0000
committerAaron Bohy <aab@odoo.com>2020-05-29 07:40:24 +0000
commit042b4060bdbbda73f5e02c902a8ecf8ab7ef96cb (patch)
tree1ecb6c88281a48daca9ceb694251821b1b5dd219 /addons/web/static/src/js/views
parente34689411c9df68229143a43415d0925972202b8 (diff)
[IMP] web: list: display adjacent buttons in same column
Adjacent buttons in the arch are now displayed in a single column in list views (main and x2many views). As soon as there is a node in-between (even if it is invisible="1"), the rule doesn't apply anymore and buttons placed before/after that node are rendered in a separated column. Task 2261774 closes odoo/odoo#51970 Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
Diffstat (limited to 'addons/web/static/src/js/views')
-rw-r--r--addons/web/static/src/js/views/list/list_renderer.js91
1 files changed, 79 insertions, 12 deletions
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 04fbb987c12..fc026a332f0 100644
--- a/addons/web/static/src/js/views/list/list_renderer.js
+++ b/addons/web/static/src/js/views/list/list_renderer.js
@@ -58,6 +58,7 @@ var ListRenderer = BasicRenderer.extend({
*/
init: function (parent, state, params) {
this._super.apply(this, arguments);
+ this._preprocessColumns();
this.columnInvisibleFields = params.columnInvisibleFields;
this.rowDecorations = this._extractDecorationAttrs(this.arch);
this.fieldDecorations = {};
@@ -283,7 +284,62 @@ var ListRenderer = BasicRenderer.extend({
};
},
/**
- * Removes the columns which should be invisible.
+ * Adjacent buttons (in the arch) are displayed in a single column. This
+ * function iterates over the arch's nodes and replaces "button" nodes by
+ * "button_group" nodes, with a single "button_group" node for adjacent
+ * "button" nodes. A "button_group" node has a "children" attribute
+ * containing all "button" nodes in the group.
+ *
+ * @private
+ */
+ _groupAdjacentButtons: function () {
+ const children = [];
+ let groupId = 0;
+ let buttonGroupNode = null;
+ for (const c of this.arch.children) {
+ if (c.tag === 'button') {
+ if (!buttonGroupNode) {
+ buttonGroupNode = {
+ tag: 'button_group',
+ children: [c],
+ attrs: {
+ name: `button_group_${groupId++}`,
+ modifiers: {},
+ },
+ };
+ children.push(buttonGroupNode);
+ } else {
+ buttonGroupNode.children.push(c);
+ }
+ } else {
+ buttonGroupNode = null;
+ children.push(c);
+ }
+ }
+ this.arch.children = children;
+ },
+ /**
+ * Processes arch's child nodes for the needs of the list view:
+ * - detects oe_read_only/oe_edit_only classnames
+ * - groups adjacent buttons in a single column.
+ * This function is executed only once, at initialization.
+ *
+ * @private
+ */
+ _preprocessColumns: function () {
+ this._processModeClassNames();
+ this._groupAdjacentButtons();
+
+ // set as readOnly (resp. editOnly) button groups containing only
+ // readOnly (resp. editOnly) buttons, s.t. no column is rendered
+ this.arch.children.filter(c => c.tag === 'button_group').forEach(c => {
+ c.attrs.editOnly = c.children.every(n => n.attrs.editOnly);
+ c.attrs.readOnly = c.children.every(n => n.attrs.readOnly);
+ });
+ },
+ /**
+ * Removes the columns which should be invisible. This function is executed
+ * at each (re-)rendering of the list.
*
* @param {Object} columnInvisibleFields contains the column invisible modifier values
*/
@@ -308,14 +364,6 @@ var ListRenderer = BasicRenderer.extend({
if (c.attrs.name in columnInvisibleFields) {
reject = columnInvisibleFields[c.attrs.name];
}
- if (c.attrs.class) {
- if (c.attrs.class.match(/\boe_edit_only\b/)) {
- c.attrs.editOnly = true;
- }
- if (c.attrs.class.match(/\boe_read_only\b/)) {
- c.attrs.readOnly = true;
- }
- }
if (!reject && c.attrs.widget === 'handle') {
self.handleField = c.attrs.name;
if (self.isGrouped) {
@@ -344,6 +392,22 @@ var ListRenderer = BasicRenderer.extend({
});
},
/**
+ * Classnames "oe_edit_only" and "oe_read_only" aim to only display the cell
+ * in the corresponding mode. This only concerns lists inside form views
+ * (for x2many fields). This function detects the className and stores a
+ * flag on the node's attrs accordingly, to ease further computations.
+ *
+ * @private
+ */
+ _processModeClassNames: function () {
+ this.arch.children.forEach(c => {
+ if (c.attrs.class) {
+ c.attrs.editOnly = /\boe_edit_only\b/.test(c.attrs.class);
+ c.attrs.readOnly = /\boe_read_only\b/.test(c.attrs.class);
+ }
+ });
+ },
+ /**
* Render a list of <td>, with aggregates if available. It can be displayed
* in the footer, or for each open groups.
*
@@ -419,7 +483,7 @@ var ListRenderer = BasicRenderer.extend({
*/
_renderBodyCell: function (record, node, colIndex, options) {
var tdClassName = 'o_data_cell';
- if (node.tag === 'button') {
+ if (node.tag === 'button_group') {
tdClassName += ' o_list_button';
} else if (node.tag === 'field') {
tdClassName += ' o_field_cell';
@@ -449,8 +513,11 @@ var ListRenderer = BasicRenderer.extend({
return $td;
}
- if (node.tag === 'button') {
- return $td.append(this._renderButton(record, node));
+ if (node.tag === 'button_group') {
+ for (const buttonNode of node.children) {
+ $td.append(this._renderButton(record, buttonNode));
+ }
+ return $td;
} else if (node.tag === 'widget') {
return $td.append(this._renderWidget(record, node));
}