[FIX] mail: make many2many_tags_email widget work

This widget hasn't been rewritten with the new views.

The purpose of this widget is to open a popup for each invalid partners
(without email) in a many2many to fill the email. If the email is not set, the
partner will not appear in the tags and its id will not be sent (which should
not be the role of a widget but that's the way it is).
This commit is contained in:
Martin Geubelle
2017-07-11 17:22:43 +02:00
parent 83e3254519
commit 8881e61ec8
3 changed files with 196 additions and 35 deletions
+112 -34
View File
@@ -1,52 +1,130 @@
odoo.define('mail.many2manytags', function (require) {
"use strict";
// FIXME: apply https://github.com/odoo/odoo/commit/1217ae914b313df7fe8511c138871e585bb21c81
var BasicModel = require('web.BasicModel');
var core = require('web.core');
var form_common = require('web.view_dialogs');
var field_registry = require('web.field_registry');
var relational_fields = require('web.relational_fields');
var M2MTags = relational_fields.FieldMany2ManyTags;
var _t = core._t;
var FieldMany2ManyTags = relational_fields.FieldMany2ManyTags;
BasicModel.include({
var FieldMany2ManyTagsEmail = FieldMany2ManyTags.extend({
init: function() {
this.values_checking = [];
this._super.apply(this, arguments);
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
add_id: function (id) {
/**
* @private
* @param {Object} record - an element from the localData
* @param {string} fieldName
* @return {Deferred<Object>} the deferred is resolved with the
* invalidPartnerIds
*/
_setInvalidMany2ManyTagsEmail: function (record, fieldName) {
var self = this;
var _super = this._super.bind(this);
// check partner has email
this.trigger_up('perform_model_rpc', {
model: 'res.partner',
method: 'search',
args: [[
["id", "=", id],
["email", "=", false],
]],
on_success: function(partner_id) {
if (partner_id.length) {
// invalid partner
var pop = new form_common.FormViewDialog(self, {
res_model: 'res.partner',
res_id: partner_id[0],
title: _t("Please complete partner's informations and Email"),
}).open();
pop.on('write_completed', self, function () {
// self.values_checking = _.without(self.values_checking, id);
_super.apply(self, [id]);
});
} else {
// valid partner
_super.apply(self, [id]);
}
var localID = (record._changes && fieldName in record._changes) ?
record._changes[fieldName] :
record.data[fieldName];
var list = this.localData[localID];
var invalidPartnerIds = [];
_.each(list.data, function (id) {
var record = self.localData[id];
if (!record.data.email) {
invalidPartnerIds.push(record);
}
});
var def;
if (invalidPartnerIds) {
// remove invalid partners
var changes = {operation: 'REMOVE', ids: _.pluck(invalidPartnerIds, 'id')};
def = this._applyX2ManyChange(record, fieldName, changes);
}
return $.when(def).then(function () {
return $.when({
invalidPartnerIds: _.pluck(invalidPartnerIds, 'res_id'),
});
});
},
});
var FieldMany2ManyTagsEmail = M2MTags.extend({
fieldsToFetch: _.extend({}, M2MTags.prototype.fieldsToFetch, {
email: {type: 'char'},
}),
specialData: "_setInvalidMany2ManyTagsEmail",
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Open a popup for each invalid partners (without email) to fill the email.
*
* @private
* @returns {Deferred}
*/
_checkEmailPopup: function () {
var self = this;
var popupDefs = [];
var validPartners = [];
// propose the user to correct invalid partners
_.each(this.record.specialData[this.name].invalidPartnerIds, function (resID) {
var def = $.Deferred();
popupDefs.push(def);
var pop = new form_common.FormViewDialog(self, {
res_model: self.field.relation,
res_id: resID,
title: _t("Please complete partner's informations and Email"),
on_saved: function (record) {
if (record.data.email) {
validPartners.push(record.res_id);
}
},
}).open();
pop.on('closed', self, function () {
def.resolve();
});
});
return $.when.apply($, popupDefs).then(function() {
// All popups have been processed for the given ids
// It is now time to set the final value with valid partners ids.
validPartners = _.uniq(validPartners);
if (validPartners.length) {
var values = _.map(validPartners, function (id) {
return {id: id};
});
self._setValue({
operation: 'ADD_M2M',
ids: values,
});
}
});
},
/**
* Override to check if all many2many values have an email set before
* rendering the widget.
*
* @override
* @private
*/
_render: function () {
var self = this;
var def = $.Deferred();
var _super = this._super.bind(this);
if (this.record.specialData[this.name].invalidPartnerIds.length) {
def = this._checkEmailPopup();
} else {
def.resolve();
}
return def.then(function () {
return _super.apply(self, arguments);
});
},
});
+82
View File
@@ -11,6 +11,7 @@ var testUtils = require('web.test_utils');
var BasicComposer = Composers.BasicComposer;
var createAsyncView = testUtils.createAsyncView;
var createView = testUtils.createView;
QUnit.module('mail', {}, function () {
@@ -862,5 +863,86 @@ QUnit.test('followers widget: do not display follower duplications', function (a
form.destroy();
});
QUnit.module('FieldMany2ManyTagsEmail', {
beforeEach: function () {
this.data = {
partner: {
fields: {
display_name: { string: "Displayed name", type: "char" },
timmy: { string: "pokemon", type: "many2many", relation: 'partner_type'},
},
records: [{
id: 1,
display_name: "first record",
timmy: [],
}],
},
partner_type: {
fields: {
name: {string: "Partner Type", type: "char"},
email: {string: "Email", type: "char"},
},
records: [
{id: 12, display_name: "gold", email: 'coucou@petite.perruche'},
{id: 14, display_name: "silver", email: ''},
]
},
};
},
});
QUnit.test('fieldmany2many tags email', function (assert) {
assert.expect(11);
var done = assert.async();
this.data.partner.records[0].timmy = [12, 14];
// the modals need to be closed before the form view rendering
createAsyncView({
View: FormView,
model: 'partner',
data: this.data,
res_id: 1,
arch:'<form string="Partners">' +
'<sheet>' +
'<field name="display_name"/>' +
'<field name="timmy" widget="many2many_tags_email"/>' +
'</sheet>' +
'</form>',
viewOptions: {
mode: 'edit',
},
mockRPC: function (route, args) {
if (args.method ==='read' && args.model === 'partner_type') {
assert.step(args.args[0]);
assert.deepEqual(args.args[1] , ['display_name', 'email'], "should read the email");
}
return this._super.apply(this, arguments);
},
archs: {
'partner_type,false,form': '<form string="Types"><field name="display_name"/><field name="email"/></form>',
},
}).then(function (form) {
// should read it 3 times (1 with the form view, one with the form dialog and one after save)
assert.verifySteps([[12, 14], [14], [14]]);
assert.strictEqual(form.$('.o_field_many2manytags[name="timmy"] span.o_tag_color_10').length, 2,
"the second tag should be present");
form.destroy();
done();
});
assert.strictEqual($('.modal-body.o_act_window').length, 1,
"there should be one modal opened to edit the empty email");
assert.strictEqual($('.modal-body.o_act_window input[name="display_name"]').val(), "silver",
"the opened modal should be a form view dialog with the partner_type 14");
assert.strictEqual($('.modal-body.o_act_window input[name="email"]').length, 1,
"there should be an email field in the modal");
// set the email and save the modal (will render the form view)
$('.modal-body.o_act_window input[name="email"]').val('coucou@petite.perruche').trigger('input');
$('.modal-footer .btn-primary').click();
});
});
});
@@ -1187,7 +1187,8 @@ var BasicModel = AbstractModel.extend({
}
var self = this;
var list = this.localData[record._changes[fieldName] || record.data[fieldName]];
var localID = (record._changes && record._changes[fieldName]) || record.data[fieldName];
var list = this.localData[localID];
var field = record.fields[fieldName];
var fieldInfo = record.fieldsInfo[viewType || record.viewType][fieldName];
var view = fieldInfo.views && fieldInfo.views[fieldInfo.mode];