[MERGE] mail, sms, mass_mailing(_sms): better manage mailing subject (mail/sms) and emojis

PURPOSE

Subject field on mailing has not the same use in email marketing (subject of
emails) and in SMS maketing (used internally as there is no subject in SMS).

Purpose of this commit is to improve mailing form view to better distinguish
email and SMS flows. Also improve use of emojis in subject and text content.

SPECIFICATIONS

This merge adds emojis to base SmsWidget in order to use a text field with
both sms and emoji widgets in "mass_mailing_sms" module for sms content.

The emoji feature is optional (depends on "enable_emojis" attribute). We
also adjust the css of emoji widget to make it suitable for a text field with
sms option.

This merge changes helper for mailing subject and update its label according
to mailing_type (mail or sms), as well as the sms content field to enable emoji
support in mailing subjects. This is done through a fake sms_subject field
that is a text without emojis while standard subject allows emojis. Helpers
depends on the displayed field.

Override CRUD to synchronize sms_subject on subject to have only one field
used to store data.

Also allow emojis in SMS content, suing the enable_emojis option.

LINKS

Task ID-2224393
PR #49096

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Odoo's Mergebot
2020-08-11 20:33:49 +02:00
committed by GitHub
11 changed files with 134 additions and 50 deletions
@@ -0,0 +1,18 @@
odoo.define('mail.field_char_emojis', function (require) {
"use strict";
var basicFields = require('web.basic_fields');
var registry = require('web.field_registry');
var FieldEmojiCommon = require('mail.field_emojis_common');
var MailEmojisMixin = require('mail.emoji_mixin');
/**
* Extension of the FieldChar that will add emojis support
*/
var FieldCharEmojis = basicFields.FieldChar.extend(MailEmojisMixin, FieldEmojiCommon);
registry.add('char_emojis', FieldCharEmojis);
return FieldCharEmojis;
});
@@ -1,10 +1,9 @@
odoo.define('mail.text_emojis_field', function (require) {
odoo.define('mail.field_emojis_common', function (require) {
"use strict";
var basicFields = require('web.basic_fields');
var core = require('web.core');
var emojis = require('mail.emojis');
var registry = require('web.field_registry');
var MailEmojisMixin = require('mail.emoji_mixin');
var _onEmojiClickMixin = MailEmojisMixin._onEmojiClick;
var QWeb = core.qweb;
@@ -24,34 +23,10 @@ var FieldEmojiCommon = {
},
/**
* This will add an emoji button that shows the emojis selection dropdown.
*
* We use 'on_attach_callback' because we need the element to be attached to the form first.
* That's because the $emojisIcon element needs to be rendered outside of this $el
* (which is an text element, that can't 'contain' any other elements).
*
* @override
*/
on_attach_callback: function () {
if (!this.$emojisIcon) {
this.$emojisIcon = $(QWeb.render('mail.EmojisDropdown', {widget: this}));
this.$emojisIcon.find('.o_mail_emoji').on('click', this._onEmojiClick.bind(this));
if (this.$el.filter('span.o_field_translate').length) {
// multi-languages activated, place the button on the left of the translation button
this.$emojisIcon.addClass('o_mail_emojis_dropdown_translation');
}
if (this.$el.filter('textarea').length) {
this.$emojisIcon.addClass('o_mail_emojis_dropdown_textarea');
}
this.$el.last().after(this.$emojisIcon);
}
if (this.mode === 'edit') {
this.$emojisIcon.show();
} else {
this.$emojisIcon.hide();
}
this._attachEmojisDropdown();
},
//--------------------------------------------------------------------------
@@ -122,22 +97,40 @@ var FieldEmojiCommon = {
*/
_triggerOnchange: function () {
this.$input.trigger('change');
},
/**
* This will add an emoji button that shows the emojis selection dropdown.
*
* Should be used inside 'on_attach_callback' because we need the element to be attached to the form first.
* That's because the $emojisIcon element needs to be rendered outside of this $el
* (which is an text element, that can't 'contain' any other elements).
*
* @private
*/
_attachEmojisDropdown: function () {
if (!this.$emojisIcon) {
this.$emojisIcon = $(QWeb.render('mail.EmojisDropdown', {widget: this}));
this.$emojisIcon.find('.o_mail_emoji').on('click', this._onEmojiClick.bind(this));
if (this.$el.filter('span.o_field_translate').length) {
// multi-languages activated, place the button on the left of the translation button
this.$emojisIcon.addClass('o_mail_emojis_dropdown_translation');
}
if (this.$el.filter('textarea').length) {
this.$emojisIcon.addClass('o_mail_emojis_dropdown_textarea');
}
this.$el.last().after(this.$emojisIcon);
}
if (this.mode === 'edit') {
this.$emojisIcon.show();
} else {
this.$emojisIcon.hide();
}
}
};
/**
* Extension of the FieldText that will add emojis support
*/
var FieldTextEmojis = basicFields.FieldText.extend(MailEmojisMixin, FieldEmojiCommon);
/**
* Extension of the FieldChar that will add emojis support
*/
var FieldCharEmojis = basicFields.FieldChar.extend(MailEmojisMixin, FieldEmojiCommon);
registry.add('text_emojis', FieldTextEmojis);
registry.add('char_emojis', FieldCharEmojis);
return {FieldTextEmojis: FieldTextEmojis, FieldCharEmojis: FieldCharEmojis};
return FieldEmojiCommon;
});
@@ -0,0 +1,18 @@
odoo.define('mail.field_text_emojis', function (require) {
"use strict";
var basicFields = require('web.basic_fields');
var registry = require('web.field_registry');
var FieldEmojiCommon = require('mail.field_emojis_common');
var MailEmojisMixin = require('mail.emoji_mixin');
/**
* Extension of the FieldText that will add emojis support
*/
var FieldTextEmojis = basicFields.FieldText.extend(MailEmojisMixin, FieldEmojiCommon);
registry.add('text_emojis', FieldTextEmojis);
return FieldTextEmojis;
});
+9
View File
@@ -17,6 +17,15 @@ $o-mail-emoji-height: 2rem;
}
}
.o_form_view {
// Emojis widgets should hide the emoji dropdown button when the field is invisible.
// This is necessary because the button is added *after* the main element (and not inside)
// (see '_attachEmojisDropdown' for more details)
.o_invisible_modifier + .o_mail_add_emoji{
display: none !important;
}
}
.o_mail_emojis_dropdown {
height: $o-mail-emoji-height;
width: 40px;
+3 -1
View File
@@ -38,7 +38,9 @@
<!-- Emojis -->
<script type="text/javascript" src="/mail/static/src/js/emojis.js"></script>
<script type="text/javascript" src="/mail/static/src/js/emojis_mixin.js"/>
<script type="text/javascript" src="/mail/static/src/js/text_emojis_fields.js"/>
<script type="text/javascript" src="/mail/static/src/js/field_emojis_common.js"/>
<script type="text/javascript" src="/mail/static/src/js/field_char_emojis.js"/>
<script type="text/javascript" src="/mail/static/src/js/field_text_emojis.js"/>
<link rel="stylesheet" type="text/scss" href="/mail/static/src/scss/emojis.scss"/>
<!-- Others -->
+1 -1
View File
@@ -66,7 +66,7 @@ class MassMailing(models.Model):
return False
active = fields.Boolean(default=True, tracking=True)
subject = fields.Char('Subject', help='Subject of emails to send', required=True, translate=True)
subject = fields.Char('Subject', help='Subject of your Mailing', required=True, translate=True)
email_from = fields.Char(string='Send From', required=True,
default=lambda self: self.env.user.email_formatted)
sent_date = fields.Datetime(string='Sent Date', copy=False)
@@ -14,7 +14,12 @@
}
}
}
.o_form_view {
// This will display the emoji widget in the right position after a text field with sms option.
.o_sms_container ~ .o_mail_add_emoji{
bottom: 55px;
}
}
.o_white_body {
background-color: white;
}
@@ -24,6 +24,15 @@ class Mailing(models.Model):
mailing_type = fields.Selection(selection_add=[
('sms', 'SMS')
], ondelete={'sms': 'set default'})
# 'sms_subject' added to override 'subject' field (string attribute should be labelled "Title" when mailing_type == 'sms').
# 'sms_subject' should have the same helper as 'subject' field when 'mass_mailing_sms' installed.
# otherwise 'sms_subject' will get the old helper from 'mass_mailing' module.
# overriding 'subject' field helper in this model is not working, since the helper will keep the new value
# even when 'mass_mailing_sms' removed (see 'mailing_mailing_view_form_sms' for more details).
sms_subject = fields.Char('Title', help='For an Email, Subject your Recipients will see in their inbox.\n'
'For an SMS Text Message, internal Title of the Message.',
related='subject', translate=True, readonly=False)
# sms options
body_plaintext = fields.Text('SMS Body', compute='_compute_body_plaintext', store=True, readonly=False)
sms_template_id = fields.Many2one('sms.template', string='SMS Template', ondelete='set null')
@@ -74,6 +83,17 @@ class Mailing(models.Model):
mail.sms_has_unregistered_account = trace_dict[mail.id]['sms_acc']
# --------------------------------------------------
# ORM OVERRIDES
# --------------------------------------------------
@api.model
def create(self, values):
# Get subject from "sms_subject" field when SMS installed (used to build the name of record in the super 'create' method)
if values.get('mailing_type') == 'sms' and values.get('sms_subject'):
values['subject'] = values['sms_subject']
return super(Mailing, self).create(values)
# --------------------------------------------------
# BUSINESS / VIEWS ACTIONS
# --------------------------------------------------
@@ -93,12 +93,22 @@
<attribute name="attrs">{'invisible': ['|',('mailing_type', '!=', 'mail'),('state', 'in', ('draft','test'))]}</attribute>
</xpath>
<!-- Form -->
<xpath expr="//field[@name='subject']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')], 'readonly': [('state', 'in', ('sending', 'done'))], 'required': [('mailing_type', '=', 'mail')]}</attribute>
<!-- overrided in xml view to prevent remaining helper changes (on mass_mailing module) when mass_mailing_sms uninstalled-->
<attribute name="help">For an Email, Subject your Recipients will see in their inbox.
For an SMS Text Message, internal Title of the Message.</attribute>
</xpath>
<xpath expr="//field[@name='subject']" position="after">
<field name="sms_subject" string="Title" attrs="{'invisible': [('mailing_type', '!=', 'sms')], 'readonly': [('state', 'in', ('sending', 'done'))], 'required': [('mailing_type', '=', 'sms')]}"/>
</xpath>
<xpath expr="//page[@name='mail_body']" position="attributes">
<attribute name="attrs">{'invisible': [('mailing_type', '!=', 'mail')]}</attribute>
</xpath>
<xpath expr="//page[@name='mail_body']" position="after">
<page string="SMS Content" name="sms_body" attrs="{'invisible': [('mailing_type', '!=', 'sms')]}">
<field name="body_plaintext" widget="sms_widget" attrs="{'required': [('mailing_type', '=', 'sms')]}"/>
<field name="body_plaintext" widget="sms_widget" attrs="{'required': [('mailing_type', '=', 'sms')]}"
options='{"enable_emojis": True}'/>
<group>
<field name="sms_force_send" invisible="1"/>
</group>
+14 -4
View File
@@ -1,11 +1,9 @@
odoo.define('sms.sms_widget', function (require) {
"use strict";
var basicFields = require('web.basic_fields');
var core = require('web.core');
var fieldRegistry = require('web.field_registry');
var FieldText = basicFields.FieldText;
var FieldTextEmojis = require('mail.field_text_emojis');
var _t = core._t;
/**
@@ -13,8 +11,9 @@ var _t = core._t;
* the number of SMS and the number of characters. This text is computed every
* time the user changes the body.
*/
var SmsWidget = FieldText.extend({
var SmsWidget = FieldTextEmojis.extend({
className: 'o_field_text',
enableEmojis: false,
/**
* @constructor
*/
@@ -23,6 +22,17 @@ var SmsWidget = FieldText.extend({
this.nbrChar = 0;
this.nbrSMS = 0;
this.encoding = 'GSM7';
this.enableEmojis = !!this.nodeOptions.enable_emojis;
},
/**
* @override
*"This will add the emoji dropdown to a target field (controlled by the "enableEmojis" attribute)
*/
on_attach_callback: function () {
if (this.enableEmojis) {
this._super.apply(this, arguments);
}
},
//--------------------------------------------------------------------------
@@ -16,7 +16,6 @@
border: 1px solid #c8c8d3;
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
background: white;
overflow: hidden;
margin: $o-sheet-vpadding*0.2 auto;
@include media-breakpoint-up(md) {