[FIX] web: fix duplication on phone+sms button rerendering

STEPS:

* Add related phone field to a form (e.g. partner_id.phone to sale.order form)
* Use widget "phone" + activate sms feature
* Create a record
* Click edit, select partner that has phone specified (e.g. +1 234), edit
partner's phone (e.g. +1 234 555), save

BEFORE: ``+1 234 []SMS`` is converted to ``+1 234 555 +1 234 555``
AFTER: ``+1 234 555 []SMS``

WHY:
* FieldPhone is inherited from FieldEmail

  https://github.com/odoo/odoo/blob/0de069b8ca9fb005ba5b076984f5677de25889ee/addons/web/static/src/js/fields/basic_fields.js#L1549

* sms module adds SMS button to ``$el``

  https://github.com/odoo/odoo/blob/0de069b8ca9fb005ba5b076984f5677de25889ee/addons/sms/static/src/js/fields_phone_widget.js#L91

* So this commit filters ``$el`` before updating it

This also solves the same issue but this time for the EmailField widget introduced at 2689915e3f

---

opw-2425949

closes odoo/odoo#65879

X-original-commit: b25104bae7f38d4d1de182176d239b1b7c8f803d
Signed-off-by: Lucas Perais (lpe) <lpe@odoo.com>
This commit is contained in:
Ivan Yelizariev
2021-02-10 13:22:36 +00:00
committed by Lucas Perais (lpe)
parent 8b67fe0b2b
commit d9ff1e6c69
4 changed files with 93 additions and 1 deletions
@@ -90,7 +90,6 @@ Phone.include({
$composerButton.on('click', this._onClickSMS.bind(this));
this.$el = this.$el.add($composerButton);
}
return def;
},
});
@@ -15,11 +15,13 @@ QUnit.module('fields', {
fields: {
message: {string: "message", type: "text"},
foo: {string: "Foo", type: "char", default: "My little Foo Value"},
mobile: {string: "mobile", type: "text"},
},
records: [{
id: 1,
message: "",
foo: 'yop',
mobile: "+32494444444",
}, {
id: 2,
message: "",
@@ -175,5 +177,53 @@ QUnit.module('fields', {
list.destroy();
});
QUnit.test('readonly sms phone field is properly rerendered after been changed by onchange', async function (assert) {
assert.expect(4);
const NEW_PHONE = '+32595555555';
const form = await createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form string="Partners">' +
'<sheet>' +
'<group>' +
'<field name="foo" on_change="1"/>' + // onchange to update mobile in readonly mode directly
'<field name="mobile" widget="phone" readonly="1"/>' + // readonly only, we don't want to go through write mode
'</group>' +
'</sheet>' +
'</form>',
res_id: 1,
viewOptions: {mode: 'edit'},
mockRPC: function (route, args) {
if (args.method === 'onchange') {
return Promise.resolve({
value: {
mobile: NEW_PHONE, // onchange to update mobile in readonly mode directly
},
});
}
return this._super.apply(this, arguments);
},
});
// check initial rendering
assert.strictEqual(form.$('.o_field_phone').text(), "+32494444444",
'Initial Phone text should be set');
assert.strictEqual(form.$('.o_field_phone_sms').text(), 'SMS',
'SMS button label should be rendered');
// trigger the onchange to update phone field, but still in readonly mode
await testUtils.fields.editInput($('input[name="foo"]'), 'someOtherFoo');
// check rendering after changes
assert.strictEqual(form.$('.o_field_phone').text(), NEW_PHONE,
'Phone text should be updated');
assert.strictEqual(form.$('.o_field_phone_sms').text(), 'SMS',
'SMS button label should not be changed');
form.destroy();
});
});
});
@@ -1588,6 +1588,7 @@ var FieldEmail = InputField.extend({
*/
_renderReadonly: function () {
if (this.value) {
this.el.innerHTML = '';
this.el.classList.add("o_form_uri", "o_text_overflow");
const anchorEl = Object.assign(document.createElement('a'), {
text: this.value,
@@ -1221,6 +1221,48 @@ QUnit.module('basic_fields', {
form.destroy();
});
QUnit.test('readonly email field field is properly rerendered after been changed by onchange', async function (assert) {
assert.expect(2);
this.data.partner.records[0].foo = 'dolores.abernathy@delos';
const form = await createView({
View: FormView,
model: 'partner',
data: this.data,
arch: '<form string="Partners">' +
'<sheet>' +
'<group>' +
'<field name="int_field" on_change="1"/>' + // onchange to update mobile in readonly mode directly
'<field name="foo" widget="email" readonly="1"/>' + // readonly only, we don't want to go through write mode
'</group>' +
'</sheet>' +
'</form>',
res_id: 1,
viewOptions: {mode: 'edit'},
mockRPC: function (route, args) {
if (args.method === 'onchange') {
return Promise.resolve({
value: {
foo: 'lara.espin@unknown', // onchange to update foo in readonly mode directly
},
});
}
return this._super.apply(this, arguments);
},
});
// check initial rendering
assert.strictEqual(form.$('.o_field_email').text(), 'dolores.abernathy@delos',
'Initial email text should be set');
// trigger the onchange to update phone field, but still in readonly mode
await testUtils.fields.editInput($('input[name="int_field"]'), '3');
// check rendering after changes
assert.strictEqual(form.$('.o_field_email').text(), 'lara.espin@unknown',
'email text should be updated');
form.destroy();
});
QUnit.module('FieldChar');