Skip to content

Commit

Permalink
[FIX] web: Add support of button type object on One2Many KanbanRecord
Browse files Browse the repository at this point in the history
Before this commit, there were a crash if you tried to add an optionnal
product in a new sale order without saving it.

Apply same logic as in the ListRenderer: buttons with type="object" are
disabled for no saved yet records, as calling the python method with no
id would make no sense.

To avoid to expose this logic inside all Kanban views, we define a
specific KanbanRecord Class for the One2many case.

This could be refactored to prevent from duplicating this logic in list
and kanban views.

Original Task ID: 1945006

closes #31695

Signed-off-by: Adrien Dieudonné (adr) <adr@odoo.com>
  • Loading branch information
res-odoo authored and adr-odoo committed Mar 22, 2019
1 parent 7269fb3 commit 230ad8c
Show file tree
Hide file tree
Showing 2 changed files with 205 additions and 0 deletions.
64 changes: 64 additions & 0 deletions addons/web/static/src/js/fields/relational_fields.js
Expand Up @@ -21,6 +21,7 @@ var dialogs = require('web.view_dialogs');
var core = require('web.core');
var data = require('web.data');
var Dialog = require('web.Dialog');
var KanbanRecord = require('web.KanbanRecord');
var KanbanRenderer = require('web.KanbanRenderer');
var ListRenderer = require('web.ListRenderer');
var Pager = require('web.Pager');
Expand Down Expand Up @@ -1397,6 +1398,59 @@ var FieldX2Many = AbstractField.extend({
},
});

var One2ManyKanbanRecord = KanbanRecord.extend({
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------

/**
* Apply same logic as in the ListRenderer: buttons with type="object"
* are disabled for no saved yet records, as calling the python method
* with no id would make no sense.
*
* To avoid to expose this logic inside all Kanban views, we define
* a specific KanbanRecord Class for the One2many case.
*
* This could be refactored to prevent from duplicating this logic in
* list and kanban views.
*
* @private
*/
_postProcessObjectButtons: function () {
var self = this;
// if the res_id is defined, it's already correctly handled by the Kanban record global event click
if (!this.state.res_id) {
this.$('.oe_kanban_action[data-type=object]').each(function (index, button) {
var $button = $(button);
if ($button.attr('warn')) {
$button.on('click', function (e) {
e.stopPropagation();
self.do_warn(_t('Warning'), _t('Please click on the "save" button first.'));
});
} else {
$button.attr('disabled', 'disabled');
}
});
}
},
/**
* @override
* @private
*/
_render: function () {
var self = this;
return this._super.apply(this, arguments).then(function () {
self._postProcessObjectButtons();
});
},
});

var One2ManyKanbanRenderer = KanbanRenderer.extend({
config: _.extend({}, KanbanRenderer.prototype.config, {
KanbanRecord: One2ManyKanbanRecord,
}),
});

var FieldOne2Many = FieldX2Many.extend({
className: 'o_field_one2many',
supportedFieldTypes: ['one2many'],
Expand Down Expand Up @@ -1450,6 +1504,16 @@ var FieldOne2Many = FieldX2Many.extend({
// Private
//--------------------------------------------------------------------------

/**
* @override
* @private
*/
_getRenderer: function () {
if (this.view.arch.tag === 'kanban') {
return One2ManyKanbanRenderer;
}
return this._super.apply(this, arguments);
},
/**
* Overrides to only render the buttons if the 'create' action is available.
*
Expand Down
Expand Up @@ -4,7 +4,9 @@ odoo.define('web.field_one_to_many_tests', function (require) {
var AbstractField = require('web.AbstractField');
var concurrency = require('web.concurrency');
var FormView = require('web.FormView');
var KanbanRecord = require('web.KanbanRecord');
var ListRenderer = require('web.ListRenderer');
var NotificationService = require('web.NotificationService');
var relationalFields = require('web.relational_fields');
var testUtils = require('web.test_utils');
var fieldUtils = require('web.field_utils');
Expand Down Expand Up @@ -5418,6 +5420,145 @@ QUnit.module('fields', {}, function () {
form.destroy();
});

QUnit.test('one2many field with virtual ids with kanban button', function (assert) {
assert.expect(25);

testUtils.mock.patch(KanbanRecord, {
init: function () {
this._super.apply(this, arguments);
this._onKanbanActionClicked = this.__proto__._onKanbanActionClicked;
},
});

this.data.partner.records[0].p = [4];

var form = createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form>' +
'<field name="p" mode="kanban">' +
'<kanban>' +
'<templates>' +
'<field name="foo"/>' +
'<t t-name="kanban-box">' +
'<div>' +
'<span><t t-esc="record.foo.value"/></span>' +
'<button type="object" class="btn btn-link fa fa-shopping-cart" name="button_warn" string="button_warn" warn="warn" />' +
'<button type="object" class="btn btn-link fa fa-shopping-cart" name="button_disabled" string="button_disabled" />' +
'</div>' +
'</t>' +
'</templates>' +
'</kanban>' +
'</field>' +
'</form>',
archs: {
'partner,false,form': '<form><field name="foo"/></form>',
},
res_id: 1,
services: {
notification: NotificationService.extend({
notify: function (params) {
assert.step(params.type);
}
}),
},
intercepts: {
execute_action: function (event) {
assert.step(event.data.action_data.name + '_' + event.data.env.model + '_' + event.data.env.currentID);
event.data.on_success();
},
},
});

// 1. Define all css selector
var oKanbanView = '.o_field_widget .o_kanban_view';
var oKanbanRecordActive = oKanbanView + ' .o_kanban_record:not(.o_kanban_ghost)';
var oAllKanbanButton = oKanbanRecordActive + ' button[data-type="object"]';
var btn1 = oKanbanRecordActive + ':nth-child(1) button[data-type="object"]';
var btn2 = oKanbanRecordActive + ':nth-child(2) button[data-type="object"]';
var btn1Warn = btn1 + '[data-name="button_warn"]';
var btn1Disabled = btn1 + '[data-name="button_disabled"]';
var btn2Warn = btn2 + '[data-name="button_warn"]';
var btn2Disabled = btn2 + '[data-name="button_disabled"]';

// check if we already have one kanban card
assert.containsOnce(form, oKanbanView, "should have one inner kanban view for the one2many field");
assert.containsOnce(form, oKanbanRecordActive, "should have one kanban records yet");

// we have 2 buttons
assert.containsN(form, oAllKanbanButton, 2, "should have 2 buttons type object");

// disabled ?
assert.containsNone(form, oAllKanbanButton + '[disabled]', "should not have button type object disabled");

// click on the button
testUtils.dom.click(form.$(btn1Disabled));
testUtils.dom.click(form.$(btn1Warn));

// switch to edit mode
testUtils.form.clickEdit(form);

// click on existing buttons
testUtils.dom.click(form.$(btn1Disabled));
testUtils.dom.click(form.$(btn1Warn));

// create new kanban
testUtils.dom.click(form.$('.o_field_widget .o-kanban-button-new'));

// save & close the modal
assert.strictEqual($('.modal-content input.o_field_widget').val(), 'My little Foo Value',
"should already have the default value for field foo");
testUtils.dom.click($('.modal-content .btn-primary').first());

// check new item
assert.containsN(form, oAllKanbanButton, 4, "should have 4 buttons type object");
assert.containsN(form, btn1, 2, "should have 2 buttons type object in area 1");
assert.containsN(form, btn2, 2, "should have 2 buttons type object in area 2");
assert.containsOnce(form, oAllKanbanButton + '[disabled]', "should have 1 button type object disabled");

assert.strictEqual(form.$(btn2Disabled).attr('disabled'), 'disabled', 'Should have a button type object disabled in area 2');
assert.strictEqual(form.$(btn2Warn).attr('disabled'), undefined, 'Should have a button type object not disabled in area 2');
assert.strictEqual(form.$(btn2Warn).attr('warn'), 'warn', 'Should have a button type object with warn attr in area 2');

// click all buttons
testUtils.dom.click(form.$(btn1Disabled));
testUtils.dom.click(form.$(btn1Warn));
testUtils.dom.click(form.$(btn2Disabled));
testUtils.dom.click(form.$(btn2Warn));

// save the form
testUtils.form.clickSave(form);

assert.containsNone(form, oAllKanbanButton + '[disabled]', "should not have button type object disabled after save");

// click all buttons
testUtils.dom.click(form.$(btn1Disabled));
testUtils.dom.click(form.$(btn1Warn));
testUtils.dom.click(form.$(btn2Disabled));
testUtils.dom.click(form.$(btn2Warn));

assert.verifySteps([
"button_disabled_partner_4",
"button_warn_partner_4",

"button_disabled_partner_4",
"button_warn_partner_4",

"button_disabled_partner_4",
"button_warn_partner_4",
"warning", // warn btn8

"button_disabled_partner_4",
"button_warn_partner_4",
"button_disabled_partner_8",
"button_warn_partner_8"
], "should have triggered theses 11 clicks event");

testUtils.mock.unpatch(KanbanRecord);
form.destroy();
});

QUnit.test('focusing fields in one2many list', function (assert) {
assert.expect(2);

Expand Down

0 comments on commit 230ad8c

Please sign in to comment.