[FIX] web: update column data when adding a record in a kanban
When a record was added in a kanban thanks to the quick create, column tooltip and column progressbar were not updating the values they showed. Now, adding/deleting records updates the whole column as the update operations. Thanks to @kig-odoo for the test. Note: to backport (partially)
This commit is contained in:
@@ -18,7 +18,6 @@ var KanbanColumn = Widget.extend({
|
|||||||
template: 'KanbanView.Group',
|
template: 'KanbanView.Group',
|
||||||
custom_events: {
|
custom_events: {
|
||||||
cancel_quick_create: '_onCancelQuickCreate',
|
cancel_quick_create: '_onCancelQuickCreate',
|
||||||
kanban_record_delete: '_onDeleteRecord',
|
|
||||||
quick_create_add_record: '_onQuickCreateAddRecord',
|
quick_create_add_record: '_onQuickCreateAddRecord',
|
||||||
tweak_column: '_onTweakColumn',
|
tweak_column: '_onTweakColumn',
|
||||||
tweak_column_records: '_onTweakColumnRecords',
|
tweak_column_records: '_onTweakColumnRecords',
|
||||||
@@ -45,7 +44,6 @@ var KanbanColumn = Widget.extend({
|
|||||||
this.id = data.res_id || value;
|
this.id = data.res_id || value;
|
||||||
this.folded = !data.isOpen;
|
this.folded = !data.isOpen;
|
||||||
this.has_active_field = 'active' in data.fields;
|
this.has_active_field = 'active' in data.fields;
|
||||||
this.size = data.count;
|
|
||||||
this.fields = data.fields;
|
this.fields = data.fields;
|
||||||
this.records = [];
|
this.records = [];
|
||||||
this.modelName = data.model;
|
this.modelName = data.model;
|
||||||
@@ -59,7 +57,7 @@ var KanbanColumn = Widget.extend({
|
|||||||
this.records_deletable = options.records_deletable;
|
this.records_deletable = options.records_deletable;
|
||||||
this.relation = options.relation;
|
this.relation = options.relation;
|
||||||
this.offset = 0;
|
this.offset = 0;
|
||||||
this.remaining = this.size - this.data_records.length;
|
this.remaining = data.count - this.data_records.length;
|
||||||
|
|
||||||
if (options.hasProgressBar) {
|
if (options.hasProgressBar) {
|
||||||
this.barOptions = {
|
this.barOptions = {
|
||||||
@@ -95,7 +93,7 @@ var KanbanColumn = Widget.extend({
|
|||||||
this.$header = this.$('.o_kanban_header');
|
this.$header = this.$('.o_kanban_header');
|
||||||
|
|
||||||
for (var i = 0; i < this.data_records.length; i++) {
|
for (var i = 0; i < this.data_records.length; i++) {
|
||||||
this.addRecord(this.data_records[i], {no_update: true});
|
this._addRecord(this.data_records[i]);
|
||||||
}
|
}
|
||||||
this.$header.find('.o_kanban_header_title').tooltip();
|
this.$header.find('.o_kanban_header_title').tooltip();
|
||||||
|
|
||||||
@@ -112,7 +110,6 @@ var KanbanColumn = Widget.extend({
|
|||||||
cursor: 'move',
|
cursor: 'move',
|
||||||
over: function () {
|
over: function () {
|
||||||
self.$el.addClass('o_kanban_hover');
|
self.$el.addClass('o_kanban_hover');
|
||||||
self._update();
|
|
||||||
},
|
},
|
||||||
out: function () {
|
out: function () {
|
||||||
self.$el.removeClass('o_kanban_hover');
|
self.$el.removeClass('o_kanban_hover');
|
||||||
@@ -145,7 +142,20 @@ var KanbanColumn = Widget.extend({
|
|||||||
defs.push(this.progressBar.appendTo(this.$header));
|
defs.push(this.progressBar.appendTo(this.$header));
|
||||||
}
|
}
|
||||||
|
|
||||||
return $.when.apply($, defs).then(this._update.bind(this));
|
var title = this.folded ? this.title + ' (' + this.data.count + ')' : this.title;
|
||||||
|
this.$header.find('.o_column_title').text(title);
|
||||||
|
|
||||||
|
this.$el.toggleClass('o_column_folded', this.folded && !config.device.isMobile);
|
||||||
|
var tooltip = this.data.count + _t(' records');
|
||||||
|
tooltip = '<p>' + tooltip + '</p>' + this.tooltipInfo;
|
||||||
|
this.$header.find('.o_kanban_header_title').tooltip({html: true}).attr('data-original-title', tooltip);
|
||||||
|
if (!this.remaining) {
|
||||||
|
this.$('.o_kanban_load_more').remove();
|
||||||
|
} else {
|
||||||
|
this.$('.o_kanban_load_more').html(QWeb.render('KanbanView.LoadMore', {widget: this}));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $.when.apply($, defs);
|
||||||
},
|
},
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
@@ -163,19 +173,30 @@ var KanbanColumn = Widget.extend({
|
|||||||
this.quickCreateWidget = new RecordQuickCreate(this, width);
|
this.quickCreateWidget = new RecordQuickCreate(this, width);
|
||||||
this.quickCreateWidget.insertAfter(this.$header);
|
this.quickCreateWidget.insertAfter(this.$header);
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* @returns {Boolean} true iff the column is empty
|
||||||
|
*/
|
||||||
|
isEmpty: function () {
|
||||||
|
return !this.records.length;
|
||||||
|
},
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
// Private
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a record in the column.
|
* Adds a record in the column.
|
||||||
*
|
*
|
||||||
|
* @private
|
||||||
* @param {Object} recordState
|
* @param {Object} recordState
|
||||||
* @param {Object} options
|
* @param {Object} [options]
|
||||||
* @params {string} options.position 'before' to add the record at the top,
|
* @param {string} [options.position]
|
||||||
* added at the bottom by default
|
* 'before' to add at the top, add at the bottom by default
|
||||||
* @params {Boolean} options.no_update set to true not to update the column
|
|
||||||
*/
|
*/
|
||||||
addRecord: function (recordState, options) {
|
_addRecord: function (recordState, options) {
|
||||||
var record = new KanbanRecord(this, recordState, this.record_options);
|
var record = new KanbanRecord(this, recordState, this.record_options);
|
||||||
this.records.push(record);
|
this.records.push(record);
|
||||||
if (options.position === 'before') {
|
if (options && options.position === 'before') {
|
||||||
record.insertAfter(this.quickCreateWidget ? this.quickCreateWidget.$el : this.$header);
|
record.insertAfter(this.quickCreateWidget ? this.quickCreateWidget.$el : this.$header);
|
||||||
} else {
|
} else {
|
||||||
var $load_more = this.$('.o_kanban_load_more');
|
var $load_more = this.$('.o_kanban_load_more');
|
||||||
@@ -185,33 +206,7 @@ var KanbanColumn = Widget.extend({
|
|||||||
record.appendTo(this.$el);
|
record.appendTo(this.$el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!options.no_update) {
|
|
||||||
this._update();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* @returns {Boolean} true iff the column is empty
|
|
||||||
*/
|
|
||||||
isEmpty: function () {
|
|
||||||
return !this.records.length;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Updates the column progressBar and sets the new data. New data are
|
|
||||||
* supposed to already match column rendering (except for the progressBar).
|
|
||||||
*
|
|
||||||
* @param {Object} data
|
|
||||||
*/
|
|
||||||
updateProgressBar: function (data) {
|
|
||||||
this.data = data;
|
|
||||||
if (!this.folded && this.progressBar) {
|
|
||||||
this.progressBar.update(this.data);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
// Private
|
|
||||||
//--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroys the QuickCreate widget.
|
* Destroys the QuickCreate widget.
|
||||||
*
|
*
|
||||||
@@ -231,25 +226,6 @@ var KanbanColumn = Widget.extend({
|
|||||||
});
|
});
|
||||||
return ids;
|
return ids;
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_update: function () {
|
|
||||||
var title = this.folded ? this.title + ' (' + this.size + ')' : this.title;
|
|
||||||
this.$header.find('.o_column_title').text(title);
|
|
||||||
this.$header.find('.o-kanban-count').text(this.records.length);
|
|
||||||
|
|
||||||
this.$el.toggleClass('o_column_folded', this.folded && !config.device.isMobile);
|
|
||||||
var tooltip = this.size + _t(' records');
|
|
||||||
tooltip = '<p>' + tooltip + '</p>' + this.tooltipInfo;
|
|
||||||
this.$header.find('.o_kanban_header_title').tooltip({html: true}).attr('data-original-title', tooltip);
|
|
||||||
if (!this.remaining) {
|
|
||||||
this.$('.o_kanban_load_more').remove();
|
|
||||||
} else {
|
|
||||||
this.$('.o_kanban_load_more').html(QWeb.render('KanbanView.LoadMore', {widget: this}));
|
|
||||||
}
|
|
||||||
this.updateProgressBar(this.data);
|
|
||||||
},
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
// Handlers
|
// Handlers
|
||||||
@@ -298,19 +274,6 @@ var KanbanColumn = Widget.extend({
|
|||||||
}),
|
}),
|
||||||
}).open();
|
}).open();
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
* @param {OdooEvent} event
|
|
||||||
*/
|
|
||||||
_onDeleteRecord: function (event) {
|
|
||||||
var self = this;
|
|
||||||
event.data.parent_id = this.db_id;
|
|
||||||
event.data.after = function cleanup() {
|
|
||||||
var index = self.records.indexOf(event.data.record);
|
|
||||||
self.records.splice(index, 1);
|
|
||||||
self._update();
|
|
||||||
};
|
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @param {MouseEvent} event
|
* @param {MouseEvent} event
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ var KanbanColumnProgressBar = Widget.extend({
|
|||||||
this._super.apply(this, arguments);
|
this._super.apply(this, arguments);
|
||||||
|
|
||||||
this.columnID = options.columnID;
|
this.columnID = options.columnID;
|
||||||
|
this.columnState = columnState;
|
||||||
|
|
||||||
// <progressbar/> attributes
|
// <progressbar/> attributes
|
||||||
this.fieldName = columnState.progressBarValues.field;
|
this.fieldName = columnState.progressBarValues.field;
|
||||||
@@ -70,37 +71,27 @@ var KanbanColumnProgressBar = Widget.extend({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._super.apply(this, arguments);
|
return this._super.apply(this, arguments).then(function () {
|
||||||
},
|
// This should be executed when the progressbar is fully rendered
|
||||||
|
// and is in the DOM, this happens to be always the case with
|
||||||
|
// current use of progressbars
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
var subgroupCounts = {};
|
||||||
// Public
|
_.each(self.colors, function (val, key) {
|
||||||
//--------------------------------------------------------------------------
|
var subgroupCount = self.columnState.progressBarValues.counts[key] || 0;
|
||||||
|
if (self.activeFilter === key && subgroupCount === 0) {
|
||||||
|
self.activeFilter = false;
|
||||||
|
}
|
||||||
|
subgroupCounts[key] = subgroupCount;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
self.groupCount = self.columnState.count;
|
||||||
* Updates internal data and rendering according to new received column
|
self.subgroupCounts = subgroupCounts;
|
||||||
* state.
|
self.prevTotalCounterValue = self.totalCounterValue;
|
||||||
*
|
self.totalCounterValue = self.sumField ? (self.columnState.aggregateValues[self.sumField] || 0) : self.columnState.count;
|
||||||
* @param {Object} columnState
|
self._notifyState();
|
||||||
*/
|
self._render();
|
||||||
update: function (columnState) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
var subgroupCounts = {};
|
|
||||||
_.each(self.colors, function (val, key) {
|
|
||||||
var subgroupCount = columnState.progressBarValues.counts[key] || 0;
|
|
||||||
if (self.activeFilter === key && subgroupCount === 0) {
|
|
||||||
self.activeFilter = false;
|
|
||||||
}
|
|
||||||
subgroupCounts[key] = subgroupCount;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.groupCount = columnState.count;
|
|
||||||
this.subgroupCounts = subgroupCounts;
|
|
||||||
this.prevTotalCounterValue = this.totalCounterValue;
|
|
||||||
this.totalCounterValue = this.sumField ? (columnState.aggregateValues[this.sumField] || 0) : columnState.count;
|
|
||||||
this._notifyState();
|
|
||||||
this._render();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//--------------------------------------------------------------------------
|
//--------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -353,10 +353,13 @@ var KanbanController = BasicController.extend({
|
|||||||
.addRecordToGroup(columnState.id, records[0])
|
.addRecordToGroup(columnState.id, records[0])
|
||||||
.then(function (db_id) {
|
.then(function (db_id) {
|
||||||
self._updateEnv();
|
self._updateEnv();
|
||||||
column.addRecord(self.model.get(db_id), {position: 'before'});
|
|
||||||
if (event.data.openRecord) {
|
var columnState = self.model.getColumn(db_id);
|
||||||
self.trigger_up('open_record', {id: db_id, mode: 'edit'});
|
return self.renderer.updateColumn(columnState.id, columnState).then(function () {
|
||||||
}
|
if (event.data.openRecord) {
|
||||||
|
self.trigger_up('open_record', {id: db_id, mode: 'edit'});
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2061,6 +2061,36 @@ QUnit.module('Views', {
|
|||||||
kanban.destroy();
|
kanban.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QUnit.test('column progressbars on quick create properly update counter', function (assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
var kanban = createView({
|
||||||
|
View: KanbanView,
|
||||||
|
model: 'partner',
|
||||||
|
data: this.data,
|
||||||
|
arch:
|
||||||
|
'<kanban>' +
|
||||||
|
'<progressbar field="foo" colors=\'{"yop": "success", "gnap": "warning", "blip": "danger"}\'/>' +
|
||||||
|
'<templates><t t-name="kanban-box">' +
|
||||||
|
'<div>' +
|
||||||
|
'<field name="name"/>' +
|
||||||
|
'</div>' +
|
||||||
|
'</t></templates>' +
|
||||||
|
'</kanban>',
|
||||||
|
groupBy: ['bar'],
|
||||||
|
});
|
||||||
|
|
||||||
|
var initialCount = parseInt(kanban.$('.o_kanban_counter_side').eq(1).text());
|
||||||
|
kanban.$('.o_kanban_quick_add').eq(1).click();
|
||||||
|
kanban.$('.o_input').val('Test');
|
||||||
|
kanban.$('.o_kanban_add').click();
|
||||||
|
var lastCount = parseInt(kanban.$('.o_kanban_counter_side').eq(1).text());
|
||||||
|
assert.strictEqual(lastCount, initialCount + 1,
|
||||||
|
"kanban counters should have updated on quick create");
|
||||||
|
|
||||||
|
kanban.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
QUnit.test('keep adding quickcreate in first column after a record from this column was moved', function (assert) {
|
QUnit.test('keep adding quickcreate in first column after a record from this column was moved', function (assert) {
|
||||||
assert.expect(2);
|
assert.expect(2);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user