[FIX] web: reimplement group_by_tooltip option in kanban
This option hadn't been implemented in the new views.
It allows to display informative explanations as tooltips on column over.
It can be set on a many2one field in the kanban view, e.g.:
```<field name="stage_id" options='{"group_by_tooltip":
{"<tooltipFieldOnStageModel>": "<ABeautifulTitle>"}
}'/>
```
An extra RPC needs to be done on the many2one relation to fetch these additional
fields and the data are stored in the datapoint under the key `tooltipData`.
This commit is contained in:
@@ -44,7 +44,6 @@ var KanbanColumn = Widget.extend({
|
||||
this.folded = !data.isOpen;
|
||||
this.has_active_field = 'active' in data.fields;
|
||||
this.size = data.count;
|
||||
this.values = data.values;
|
||||
this.fields = data.fields;
|
||||
this.records = [];
|
||||
this.modelName = data.model;
|
||||
@@ -62,13 +61,12 @@ var KanbanColumn = Widget.extend({
|
||||
|
||||
this.record_options = _.clone(recordOptions);
|
||||
|
||||
if (data.options && data.options.group_by_tooltip) {
|
||||
var self = this;
|
||||
this.tooltip_info = _.map(data.options.group_by_tooltip, function (key, value) {
|
||||
return (self.values && self.values[value] && "<div>" +key + "<br>" + self.values[value] + "</div>") || '';
|
||||
if (options.group_by_tooltip) {
|
||||
this.tooltipInfo = _.map(options.group_by_tooltip, function (help, field) {
|
||||
return (data.tooltipData && data.tooltipData[field] && "<div>" + help + "<br>" + data.tooltipData[field] + "</div>") || '';
|
||||
}).join('');
|
||||
} else {
|
||||
this.tooltip_info = "";
|
||||
this.tooltipInfo = "";
|
||||
}
|
||||
},
|
||||
/**
|
||||
@@ -216,7 +214,7 @@ var KanbanColumn = Widget.extend({
|
||||
|
||||
this.$el.toggleClass('o_column_folded', this.folded);
|
||||
var tooltip = this.size + _t(' records');
|
||||
tooltip = '<p>' + tooltip + '</p>' + this.tooltip_info;
|
||||
tooltip = '<p>' + tooltip + '</p>' + this.tooltipInfo;
|
||||
this.$header.tooltip({html: true}).attr('data-original-title', tooltip);
|
||||
if (!this.remaining) {
|
||||
this.$('.o_kanban_load_more').remove();
|
||||
|
||||
@@ -89,6 +89,21 @@ var KanbanModel = BasicModel.extend({
|
||||
return newGroup.id;
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Add the key `tooltipData` (kanban specific) when performing a `geŧ`.
|
||||
*
|
||||
* @override
|
||||
* @see _readTooltipFields
|
||||
* @returns {Object}
|
||||
*/
|
||||
get: function () {
|
||||
var result = this._super.apply(this, arguments);
|
||||
var dp = result && this.localData[result.id];
|
||||
if (dp && dp.tooltipData) {
|
||||
result.tooltipData = $.extend(true, {}, dp.tooltipData);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
@@ -203,10 +218,55 @@ var KanbanModel = BasicModel.extend({
|
||||
* @param {Object} list valid resource object
|
||||
*/
|
||||
_readGroup: function (list) {
|
||||
var self = this;
|
||||
if (list.groupedBy.length > 1) {
|
||||
list.groupedBy = [list.groupedBy[0]];
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
return this._super.apply(this, arguments).then(function (result) {
|
||||
return self._readTooltipFields(list).then(_.constant(result));
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Fetches tooltip specific fields on the group by relation and stores it in
|
||||
* the column datapoint in a special key `tooltipData`.
|
||||
* Data for the tooltips (group_by_tooltip) are fetched in batch for all
|
||||
* groups, to avoid doing multiple calls.
|
||||
* Data are stored in a special key `tooltipData` on the datapoint.
|
||||
* Note that the option `group_by_tooltip` is only for m2o fields.
|
||||
*
|
||||
* @private
|
||||
* @param {Object} list a list of groups
|
||||
* @returns {Deferred}
|
||||
*/
|
||||
_readTooltipFields: function (list) {
|
||||
var self = this;
|
||||
var groupedByField = list.fields[list.groupedBy[0]];
|
||||
if (groupedByField.type !== 'many2one') {
|
||||
return $.when();
|
||||
}
|
||||
var groupIds = _.map(list.data, function (id) {
|
||||
return self.get(id, {raw: true}).res_id;
|
||||
});
|
||||
var tooltipFields = [];
|
||||
var groupedByFieldInfo = list.fieldsInfo.kanban[list.groupedBy[0]];
|
||||
if (groupedByFieldInfo && groupedByFieldInfo.options) {
|
||||
tooltipFields = Object.keys(groupedByFieldInfo.options.group_by_tooltip || {});
|
||||
}
|
||||
if (groupIds.length && tooltipFields.length) {
|
||||
var fieldNames = _.union(['display_name'], tooltipFields);
|
||||
return this._rpc({
|
||||
model: groupedByField.relation,
|
||||
method: 'read',
|
||||
args: [groupIds, fieldNames],
|
||||
context: list.context,
|
||||
}).then(function (result) {
|
||||
_.each(list.data, function (id) {
|
||||
var dp = self.localData[id];
|
||||
dp.tooltipData = _.findWhere(result, {id: dp.res_id});
|
||||
});
|
||||
});
|
||||
}
|
||||
return $.when();
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -188,6 +188,7 @@ var KanbanRenderer = BasicRenderer.extend({
|
||||
_renderGrouped: function (fragment) {
|
||||
var self = this;
|
||||
var groupByFieldAttrs = this.state.fields[this.state.groupedBy[0]];
|
||||
var groupByFieldInfo = this.state.fieldsInfo.kanban[this.state.groupedBy[0]];
|
||||
// Deactivate the drag'n'drop if the groupedBy field:
|
||||
// - is a date or datetime since we group by month or
|
||||
// - is readonly
|
||||
@@ -201,8 +202,10 @@ var KanbanRenderer = BasicRenderer.extend({
|
||||
}
|
||||
var groupedByM2O = groupByFieldAttrs && (groupByFieldAttrs.type === 'many2one');
|
||||
var grouped_by_field = groupedByM2O && groupByFieldAttrs.relation;
|
||||
var groupByTooltip = groupByFieldInfo && groupByFieldInfo.options.group_by_tooltip;
|
||||
this.columnOptions = _.extend(this.columnOptions, {
|
||||
draggable: draggable,
|
||||
group_by_tooltip: groupByTooltip,
|
||||
grouped_by_m2o: groupedByM2O,
|
||||
relation: grouped_by_field,
|
||||
});
|
||||
|
||||
@@ -55,6 +55,7 @@ QUnit.module('Views', {
|
||||
limit: 40,
|
||||
modelName: 'partner',
|
||||
openGroupByDefault: true,
|
||||
viewType: 'kanban',
|
||||
};
|
||||
}
|
||||
}, function () {
|
||||
|
||||
@@ -1491,6 +1491,43 @@ QUnit.module('Views', {
|
||||
"Create button should now be highlighted");
|
||||
kanban.destroy();
|
||||
});
|
||||
|
||||
QUnit.test('group_by_tooltip option when grouping on a many2one', function (assert) {
|
||||
assert.expect(5);
|
||||
var kanban = createView({
|
||||
View: KanbanView,
|
||||
model: 'partner',
|
||||
data: this.data,
|
||||
arch: '<kanban default_group_by="bar">' +
|
||||
'<field name="bar"/>' +
|
||||
'<field name="product_id" '+
|
||||
'options=\'{"group_by_tooltip": {"name": "Kikou"}}\'/>' +
|
||||
'<templates><t t-name="kanban-box">' +
|
||||
'<div><field name="foo"/></div>' +
|
||||
'</t></templates></kanban>',
|
||||
mockRPC: function (route, args) {
|
||||
if (route === '/web/dataset/call_kw/product/read') {
|
||||
assert.strictEqual(args.args[0].length, 2,
|
||||
"read on two groups");
|
||||
assert.deepEqual(args.args[1], ['display_name', 'name'],
|
||||
"should read on specified fields on the group by relation");
|
||||
}
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
});
|
||||
|
||||
assert.strictEqual(kanban.$('.o_kanban_group').length, 2, "should have " + 2 + " columns");
|
||||
|
||||
// simulate an update coming from the searchview, with another groupby given
|
||||
kanban.update({groupBy: ['product_id']});
|
||||
assert.ok(kanban.$('.o_kanban_group:first span.o_column_title:contains(hello)').length,
|
||||
"first column should have a title with a value from the many2one");
|
||||
assert.strictEqual(kanban.$('.o_kanban_group:first .o_kanban_header').data('original-title'),
|
||||
"<p>2 records</p><div>Kikou<br>hello</div>",
|
||||
"first column should have a tooltip with the number of records, the group_by_tooltip title and many2one field value");
|
||||
|
||||
kanban.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user