[IMP] website_mass_mailing, *: improve newsletter snippets

* website, mass_mailing, web_editor

This commit adds various improvements in newsletter snippets as follow:

- Improves UI for newsletter popup.

- We only had one popup for all websites. Now, we can have a different
popup for each website.

- The popup was not appearing on mobile/tablet devices. Now, in
mobile/tablet devices, the popup appears automatically after 5secs.

- Added the ability to customize the whole editor popup like any
editable area (background colors, etc).

- User needed to enable popup snippet from the settings. We removed that
setting so now popup snippet will always be available.

- Added new snippet "Newsletter block".

- Display notification after successful subscription the same way for
all newsletter snippets.

Closes https://github.com/odoo/odoo/pull/29353
task-1903256

closes odoo/odoo#29353

Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>


Co-authored-by: qsm-odoo <qsm@odoo.com>
This commit is contained in:
Kishan Gajjar
2019-06-25 09:20:35 +00:00
committed by qsm-odoo
co-authored by qsm-odoo
parent 2ad49ec93e
commit 34c4b3ad8a
27 changed files with 442 additions and 544 deletions
@@ -58,8 +58,6 @@
</div>
</div>
</div>
<h2>Mailing Lists</h2>
<div id="mailing_list" class="row mt16 o_settings_container"/>
</div>
</xpath>
</field>
@@ -188,13 +188,14 @@ var Wysiwyg = Widget.extend({
*
* @param {object} [options]
* @param {Boolean} [options.keepPopover]
* @param {jQueryElement} [options.$layout]
* @returns {String}
*/
getValue: function (options) {
if (!options || !options.keepPopover) {
this._summernote.invoke('editor.hidePopover');
}
var $editable = this.getEditable().clone();
var $editable = options && options.$layout || this.getEditable().clone();
$editable.find('.o_wysiwyg_to_remove').remove();
$editable.find('[contenteditable]').removeAttr('contenteditable');
$editable.find('.o_fake_not_editable').removeClass('o_fake_not_editable');
+1 -1
View File
@@ -24,7 +24,6 @@
<t t-call="web._assets_helpers">
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/bootstrap_overridden.scss"/>
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/wysiwyg_variables.scss"/>
</t>
<!-- integration -->
@@ -91,6 +90,7 @@
<template id="_assets_primary_variables" inherit_id="web._assets_primary_variables">
<xpath expr="//link[last()]" position="after">
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/web_editor.variables.scss"/>
<link rel="stylesheet" type="text/scss" href="/web_editor/static/src/scss/wysiwyg_variables.scss"/>
</xpath>
</template>
+7
View File
@@ -289,6 +289,13 @@
<field name="type">url</field>
<field name="url">/website/static/src/img/library/wine.jpg</field>
</record>
<record id="website.library_image_17" model="ir.attachment">
<field name="public" eval="True"/>
<field name="name">marketing.jpg</field>
<field name="res_model">ir.ui.view</field>
<field name="type">url</field>
<field name="url">/website/static/src/img/library/marketing.jpg</field>
</record>
<!-- Website Builder Background Images -->
<record id="website.s_background_image_01" model="ir.attachment">
Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 960 B

@@ -24,6 +24,7 @@ var EditorMenu = Widget.extend({
},
custom_events: {
request_save: '_onSnippetRequestSave',
get_clean_html: '_onGetCleanHTML',
},
/**
@@ -197,6 +198,15 @@ var EditorMenu = Widget.extend({
_onCancelClick: function () {
this.cancel(false);
},
/**
* Get the cleaned value of the editable element.
*
* @private
* @param {OdooEvent} ev
*/
_onGetCleanHTML: function (ev) {
ev.data.callback(this.wysiwyg.getValue({$layout: ev.data.$layout}));
},
/**
* Snippet (menu_data) can request to save the document to leave the page
*
@@ -339,3 +339,19 @@ table.editorbar-panel {
cursor: pointer;
}
}
// User modal in edit mode
.editor_enable, .note-editable {
.modal:not(.o_technical_modal) {
top: 40px;
right: 0;
bottom: 0;
left: $o-we-sidebar-width;
width: auto;
height: auto;
.modal-dialog {
padding: 0.5rem 0; // To use more editor space if necessary
}
}
}
+6 -3
View File
@@ -892,6 +892,8 @@
<template id="external_snippets" inherit_id="website.snippets" priority="8">
<xpath expr="//div[@id='snippet_feature']//t[@t-snippet][last()]" position="after">
<t id="newsletter_popup_snippet" t-install="mass_mailing" string="Newsletter Popup" t-thumbnail="/website/static/src/img/snippets_thumbs/newsletter_subscribe_popup.png"/>
<t id="newsletter_block_snippet" t-install="mass_mailing" string="Newsletter Block" t-thumbnail="/website/static/src/img/snippets_thumbs/s_newsletter_block.png"/>
<t t-install="website_twitter" string="Twitter Scroller" t-thumbnail="/website/static/src/img/snippets_thumbs/s_twitter_scroll.png"/>
<t t-install="website_form" string="Form Builder" t-thumbnail="/website/static/src/img/s_website_form.png"/>
<t id="s_products_searchbar" t-install="website_sale" string="Products Search" t-thumbnail="/website/static/src/img/snippets_thumbs/s_products_searchbar.png"/>
@@ -899,7 +901,7 @@
<xpath expr="//div[@id='snippet_content']//t[@t-snippet][last()]" position="after">
<t t-install="website_event" string="Local Events" t-thumbnail="/website/static/src/img/snippets_thumbs/s_local_events.png"/>
<t t-install="website_mail_channel" string="Discussion Group" t-thumbnail="/website/static/src/img/snippets_thumbs/s_button_channel_subscribe.png"/>
<t t-install="mass_mailing" string="Newsletter" t-thumbnail="/website/static/src/img/snippets_thumbs/s_newsletter_subscribe_form.png"/>
<t id="newsletter_snippet" t-install="mass_mailing" string="Newsletter" t-thumbnail="/website/static/src/img/snippets_thumbs/s_newsletter_subscribe_form.png"/>
<t id="s_products_searchbar_input" t-install="website_sale" string="Products Search Input" t-thumbnail="/website/static/src/img/snippets_thumbs/s_products_searchbar.png"/>
</xpath>
</template>
@@ -1213,7 +1215,7 @@
</div>
<!-- V-ALIGN -->
<div data-selector=".s_text_image, .s_image_text, .s_three_columns" data-target=".row">
<div id="row_valign_snippet_option" data-selector=".s_text_image, .s_image_text, .s_three_columns" data-target=".row">
<div class="dropdown-submenu">
<a tabindex="-2" href="#" class="dropdown-item"><i class="fa fa-arrows-v"/>Alignment</a>
<div class="dropdown-menu" role="menu">
@@ -1354,7 +1356,8 @@
<!-- Anchor Name -->
<div data-js="anchorName"
data-selector=":not(p).oe_structure > *, :not(p)[data-oe-type=html] > *, .row > div">
data-selector=":not(p).oe_structure > *, :not(p)[data-oe-type=html] > *, .row > div"
data-exclude=".modal *">
<a tabindex="-1" href="#" class="dropdown-item" data-no-preview="true" data-open-anchor-dialog=""><i class="fa fa-anchor"/>Anchor Name</a>
</div>
</template>
+1 -2
View File
@@ -12,11 +12,10 @@ On a simple click, your visitors can subscribe to mailing lists managed in the E
'category': 'Website',
'depends': ['website', 'mass_mailing'],
'data': [
'security/mass_mailing_security.xml',
'security/ir.model.access.csv',
'views/website_mass_mailing_templates.xml',
'views/snippets_templates.xml',
'views/mass_mailing_view.xml',
'views/res_config_settings_views.xml',
],
'qweb': [
'static/src/xml/*.xml',
@@ -2,6 +2,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.http import route, request
from odoo.osv import expression
from odoo.addons.mass_mailing.controllers.main import MassMailController
@@ -39,12 +40,32 @@ class MassMailController(MassMailController):
list_contact_rel.opt_out = False
# add email to session
request.session['mass_mailing_email'] = email
return True
mass_mailing_list = request.env['mail.mass_mailing.list'].sudo().browse(list_id)
return {'toast_content': mass_mailing_list.toast_content}
@route(['/website_mass_mailing/get_content'], type='json', website=True, auth="public")
def get_mass_mailing_content(self, newsletter_id, **post):
PopupModel = request.env['website.mass_mailing.popup'].sudo()
data = self.is_subscriber(newsletter_id, **post)
mass_mailing_list = request.env['mail.mass_mailing.list'].sudo().browse(int(newsletter_id))
data['content'] = mass_mailing_list.popup_content,
data['redirect_url'] = mass_mailing_list.popup_redirect_url
domain = expression.AND([request.website.website_domain(), [('mailing_list_id', '=', newsletter_id)]])
mass_mailing_popup = PopupModel.search(domain, limit=1)
if mass_mailing_popup:
data['popup_content'] = mass_mailing_popup.popup_content
else:
data.update(PopupModel.default_get(['popup_content']))
return data
@route(['/website_mass_mailing/set_content'], type='json', website=True, auth="user")
def set_mass_mailing_content(self, newsletter_id, content, **post):
PopupModel = request.env['website.mass_mailing.popup']
domain = expression.AND([request.website.website_domain(), [('mailing_list_id', '=', newsletter_id)]])
mass_mailing_popup = PopupModel.search(domain, limit=1)
if mass_mailing_popup:
mass_mailing_popup.write({'popup_content': content})
else:
PopupModel.create({
'mailing_list_id': newsletter_id,
'popup_content': content,
'website_id': request.website.id,
})
return True
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import res_config_settings
from . import mass_mailing_list
@@ -7,17 +7,20 @@ from odoo import fields, models
class MassMailingList(models.Model):
_inherit = 'mail.mass_mailing.list'
def _default_popup_content(self):
return """<div class="modal-header text-center">
<h3 class="modal-title mt8">Odoo Presents</h3>
</div>
<div class="o_popup_message">
<font>7</font>
<strong>Business Hacks</strong>
<span> to<br/>boost your marketing</span>
</div>
<p class="o_message_paragraph">Join our Marketing newsletter and get <strong>this white paper instantly</strong></p>"""
def _default_toast_content(self):
return '<p>Thanks for subscribing!</p>'
popup_content = fields.Html(string="Website Popup Content", translate=True, sanitize_attributes=False,
default=_default_popup_content)
popup_redirect_url = fields.Char(string="Website Popup Redirect URL", default='/')
website_popup_ids = fields.One2many('website.mass_mailing.popup', 'mailing_list_id', string="Website Popups")
toast_content = fields.Html(default=_default_toast_content, translate=True)
class MassMailingPopup(models.Model):
_name = 'website.mass_mailing.popup'
_description = "Mailing list popup"
def _default_popup_content(self):
return self.env['ir.ui.view'].render_template('website_mass_mailing.s_newsletter_block')
mailing_list_id = fields.Many2one('mail.mass_mailing.list')
website_id = fields.Many2one('website')
popup_content = fields.Html(string="Website Popup Content", default=_default_popup_content, translate=True, sanitize=False)
@@ -1,10 +0,0 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
group_website_popup_on_exit = fields.Boolean(string="Website Popup", implied_group="website_mass_mailing.group_website_popup_on_exit")
@@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_mass_mailing_popup,website.mail.popup,model_website_mass_mailing_popup,mass_mailing.group_mass_mailing_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_mass_mailing_popup website.mail.popup model_website_mass_mailing_popup mass_mailing.group_mass_mailing_user 1 1 1 1
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="group_website_popup_on_exit" model="res.groups">
<field name="name">Use subscription pop up on the website</field>
<field name="category_id" ref="base.module_category_hidden"/>
</record>
</odoo>
@@ -1,261 +0,0 @@
/* Summernote not Support for placeholder text https://github.com/summernote/summernote/issues/581 */
.editor_enable [data-oe-placeholder]:empty:not(:focus):before {
content: " \00a0 " attr(data-oe-placeholder);
opacity: 0.4;
}
.o_popup_animated {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}
@-webkit-keyframes o_popup_bounce_small {
0%,
20%,
53%,
80%,
100% {
-webkit-transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
40%,
43% {
-webkit-transition-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
transition-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
-webkit-transform: translate3d(0, -14px, 0);
transform: translate3d(0, -14px, 0);
}
70% {
-webkit-transition-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
transition-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
-webkit-transform: translate3d(0, -8px, 0);
transform: translate3d(0, -8px, 0);
}
90% {
-webkit-transform: translate3d(0, -2px, 0);
transform: translate3d(0, -2px, 0);
}
}
@keyframes o_popup_bounce_small {
0%,
20%,
53%,
80%,
100% {
-webkit-transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
-webkit-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
40%,
43% {
-webkit-transition-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
transition-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
-webkit-transform: translate3d(0, -14px, 0);
transform: translate3d(0, -14px, 0);
}
70% {
-webkit-transition-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
transition-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06);
-webkit-transform: translate3d(0, -8px, 0);
transform: translate3d(0, -8px, 0);
}
90% {
-webkit-transform: translate3d(0, -2px, 0);
transform: translate3d(0, -2px, 0);
}
}
.o_popup_bounce_small {
-webkit-animation-name: o_popup_bounce_small;
animation-name: o_popup_bounce_small;
-webkit-transform-origin: center bottom;
-ms-transform-origin: center bottom;
transform-origin: center bottom;
}
.o_popup_bounce_del500ms {
-webkit-animation-delay: 500ms;
animation-delay: 500ms;
}
#o_newsletter_popup .btn.btn-success {
color: #ffffff;
background-color: #21b799;
border-color: #1da187;
}
#o_newsletter_popup .btn.btn-success:hover,
#o_newsletter_popup .btn.btn-success:focus,
#o_newsletter_popup .btn.btn-success.focus,
#o_newsletter_popup .btn.btn-success:active,
#o_newsletter_popup .btn.btn-success.active,
.open > .dropdown-toggle#o_newsletter_popup .btn.btn-success {
color: #ffffff;
background-color: #198c75;
border-color: #146e5c;
}
#o_newsletter_popup .btn.btn-success:active,
#o_newsletter_popup .btn.btn-success.active,
.open > .dropdown-toggle#o_newsletter_popup .btn.btn-success {
background-image: none;
}
#o_newsletter_popup .btn.btn-success.disabled,
#o_newsletter_popup .btn.btn-success[disabled],
fieldset[disabled] #o_newsletter_popup .btn.btn-success,
#o_newsletter_popup .btn.btn-success.disabled:hover,
#o_newsletter_popup .btn.btn-success[disabled]:hover,
fieldset[disabled] #o_newsletter_popup .btn.btn-success:hover,
#o_newsletter_popup .btn.btn-success.disabled:focus,
#o_newsletter_popup .btn.btn-success[disabled]:focus,
fieldset[disabled] #o_newsletter_popup .btn.btn-success:focus,
#o_newsletter_popup .btn.btn-success.disabled.focus,
#o_newsletter_popup .btn.btn-success[disabled].focus,
fieldset[disabled] #o_newsletter_popup .btn.btn-success.focus,
#o_newsletter_popup .btn.btn-success.disabled:active,
#o_newsletter_popup .btn.btn-success[disabled]:active,
fieldset[disabled] #o_newsletter_popup .btn.btn-success:active,
#o_newsletter_popup .btn.btn-success.disabled.active,
#o_newsletter_popup .btn.btn-success[disabled].active,
fieldset[disabled] #o_newsletter_popup .btn.btn-success.active {
background-color: #21b799;
border-color: #1da187;
}
#o_newsletter_popup h1,
#o_newsletter_popup h2,
#o_newsletter_popup h3,
#o_newsletter_popup h4,
#o_newsletter_popup h5,
#o_newsletter_popup h6,
#o_newsletter_popup .h1,
#o_newsletter_popup .h2,
#o_newsletter_popup .h3,
#o_newsletter_popup .h4,
#o_newsletter_popup .h5,
#o_newsletter_popup .h6 {
font-weight: 300;
color: #666;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
#o_newsletter_popup h1:first-child,
#o_newsletter_popup h2:first-child,
#o_newsletter_popup h3:first-child,
#o_newsletter_popup h4:first-child,
#o_newsletter_popup h5:first-child,
#o_newsletter_popup h6:first-child,
#o_newsletter_popup .h1:first-child,
#o_newsletter_popup .h2:first-child,
#o_newsletter_popup .h3:first-child,
#o_newsletter_popup .h4:first-child,
#o_newsletter_popup .h5:first-child,
#o_newsletter_popup .h6:first-child {
margin-top: 0;
}
#o_newsletter_popup .o_popup_modal_content {
border-radius: 2px;
box-shadow: 0 0 20px rgba(255, 255, 255, 0.11);
-webkit-box-shadow: 0 0 20px rgba(255, 255, 255, 0.11);
border: 1px solid #767676;
background: #f2f2f2;
}
#o_newsletter_popup .o_popup_modal_content:before {
content: "";
position: absolute;
width: 100%;
height: 100%;
z-index: 0;
background: -moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 0) 100%);
background: -webkit-gradient(linear, left top, right bottom, color-stop(0%, rgba(255, 255, 255, 0.3)), color-stop(42%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
background: -webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 0) 100%);
background: -o-linear-gradient(-45deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 0) 100%);
background: -ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 0) 100%);
background: linear-gradient(135deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0) 42%, rgba(255, 255, 255, 0) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#00ffffff', GradientType=1);
}
#web_editor_inside_iframe #o_newsletter_popup .o_popup_modal_content:before {
content: none;
}
#o_newsletter_popup .o_popup_modal_content .o_popup_modal_header {
background: #6c1153;
padding: 5px;
}
#o_newsletter_popup .o_popup_modal_content .o_popup_modal_header .o_popup_modal_title {
color: #ffffff;
}
#o_newsletter_popup .o_popup_modal_content .o_popup_modal_header * {
position: relative;
z-index: 1;
}
#o_newsletter_popup .o_popup_modal_content a.o_popup_btn_close {
position: absolute;
z-index: 99;
right: 5px;
top: 6px;
width: 23px;
height: 23px;
display: block;
text-align: center;
border-radius: 100em;
background: #6c1153;
color: #daa3cb;
text-decoration: none;
-webkit-transition: all ease 200ms;
-moz-transition: all ease 200ms;
-ms-transition: all ease 200ms;
-o-transition: all ease 200ms;
}
#o_newsletter_popup .o_popup_modal_content a.o_popup_btn_close:hover {
background: #89296e;
color: #ffffff;
}
#o_newsletter_popup .o_popup_modal_content .o_popup_modal_body {
padding: 0px 0px 30px;
color: #666666;
}
#o_newsletter_popup .o_popup_modal_content .o_popup_modal_body .o_popup_content_dev {
padding-bottom: 15px;
}
#o_newsletter_popup .o_popup_modal_content .o_popup_modal_body .o_popup_content_dev .o_popup_message {
font-size: 3em;
position: relative;
text-align: left;
padding-left: 2em;
line-height: 1;
margin: .5em;
font-weight: 100;
}
#o_newsletter_popup .o_popup_modal_content .o_popup_modal_body .o_popup_content_dev .o_popup_message font {
font-weight: 600;
color: #875A7B;
font-size: 2.5em;
font-style: italic;
position: absolute;
top: -0.1em;
margin-left: -0.65em;
}
#o_newsletter_popup .o_popup_modal_content .o_popup_modal_body .o_popup_content_dev .o_popup_message strong {
color: #875A7B;
}
#o_newsletter_popup .o_popup_modal_content .o_popup_modal_body .o_popup_content_dev .o_message_paragraph {
position: relative;
}
#o_newsletter_popup .o_popup_modal_content .o_popup_modal_body .input-group {
margin-left: auto;
margin-right: auto;
max-width: 350px;
}
#o_newsletter_popup .o_popup_modal_content .o_popup_modal_body .input-group input {
border-radius: 2px 0 0 2px;
border: none;
outline: 0;
box-shadow: inset 0 -1px #cccccc;
}
#o_newsletter_popup .o_popup_modal_content .o_popup_modal_body .input-group .btn {
border-radius: 0 2px 2px 0;
border-width: 0 0 1px;
padding-top: 7px;
margin-left: -1px;
-webkit-transition: all ease 200ms;
-moz-transition: all ease 200ms;
-ms-transition: all ease 200ms;
-o-transition: all ease 200ms;
}
@@ -1,7 +1,6 @@
odoo.define('website_mass_mailing.editor', function (require) {
'use strict';
var ajax = require('web.ajax');
var core = require('web.core');
var rpc = require('web.rpc');
var WysiwygMultizone = require('web_editor.wysiwyg.multizone');
@@ -10,22 +9,35 @@ var wUtils = require('website.utils');
var _t = core._t;
var mass_mailing_common = options.Class.extend({
options.registry.mailing_list_subscribe = options.Class.extend({
popup_template_id: "editor_new_mailing_list_subscribe_button",
popup_title: _t("Add a Newsletter Subscribe Button"),
//--------------------------------------------------------------------------
// Options
//--------------------------------------------------------------------------
/**
* Allows to select mailing list.
*
* @see this.selectClass for parameters
*/
select_mailing_list: function (previewMode, value) {
var self = this;
var def = wUtils.prompt({
'id': this.popup_template_id,
'window_title': this.popup_title,
'select': _t("Newsletter"),
'init': function (field) {
'init': function (field, dialog) {
return rpc.query({
model: 'mail.mass_mailing.list',
method: 'name_search',
args: ['', []],
context: self.options.recordInfo.context,
});
model: 'mail.mass_mailing.list',
method: 'name_search',
args: ['', [['is_public', '=', true]]],
context: self.options.recordInfo.context,
}).then(function (data) {
$(dialog).find('.btn-primary').prop('disabled', !data.length);
return data;
});
},
});
def.then(function (result) {
@@ -33,6 +45,9 @@ var mass_mailing_common = options.Class.extend({
});
return def;
},
/**
* @override
*/
onBuilt: function () {
var self = this;
this._super();
@@ -42,75 +57,95 @@ var mass_mailing_common = options.Class.extend({
},
});
options.registry.mailing_list_subscribe = mass_mailing_common.extend({
cleanForSave: function () {
this.$target.addClass('d-none');
},
});
options.registry.newsletter_popup = mass_mailing_common.extend({
options.registry.newsletter_popup = options.registry.mailing_list_subscribe.extend({
popup_template_id: "editor_new_mailing_list_subscribe_popup",
popup_title: _t("Add a Newsletter Subscribe Popup"),
select_mailing_list: function (previewMode, value) {
/**
* @override
*/
start: function () {
var self = this;
return this._super(previewMode, value).then(function (mailing_list_id) {
ajax.jsonRpc('/web/dataset/call', 'call', {
model: 'mail.mass_mailing.list',
method: 'read',
args: [[parseInt(mailing_list_id)], ['popup_content'], self.options.recordInfo.context],
}).then(function (data) {
self.$target.find(".o_popup_content_dev").empty();
if (data && data[0].popup_content) {
$(data[0].popup_content).appendTo(self.$target.find(".o_popup_content_dev"));
}
this.$target.on('click.newsletter_popup_option', '.o_edit_popup', function (ev) {
// So that the snippet is not enabled again by the editor
ev.stopPropagation();
self.$target.data('quick-open', true);
self._refreshPublicWidgets();
});
this.$target.on('shown.bs.modal.newsletter_popup_option hide.bs.modal.newsletter_popup_option', function () {
self.$target.closest('.o_editable').trigger('content_changed');
self.trigger_up('deactivate_snippet');
});
return this._super.apply(this, arguments);
},
/**
* @override
*/
cleanForSave: function () {
var self = this;
var content = this.$target.data('content');
if (content) {
this.trigger_up('get_clean_html', {
$layout: $('<div/>').html(content),
callback: function (html) {
self.$target.data('content', html);
},
});
}
this._super.apply(this, arguments);
},
/**
* @override
*/
destroy: function () {
this.$target.off('.newsletter_popup_option');
this._super.apply(this, arguments);
},
//--------------------------------------------------------------------------
// Options
//--------------------------------------------------------------------------
/**
* @override
*/
select_mailing_list: function () {
var self = this;
return this._super.apply(this, arguments).then(function () {
self.$target.data('quick-open', true);
self.$target.removeData('content');
self._refreshPublicWidgets();
});
},
});
WysiwygMultizone.include({
events: _.extend({}, WysiwygMultizone.prototype.events, {
'click #edit_dialog': 'edit_dialog',
'click .o_popup_modal_content [data-dismiss="modal"]': 'close_dialog',
}),
save: function () {
var $target = $('#wrapwrap').find('#o_newsletter_popup');
if ($target && $target.length) {
this.close_dialog();
$('.o_popup_bounce_small').show();
if (!$target.find('.o_popup_content_dev').length) {
$target.find('.o_popup_modal_body').prepend($('<div class="o_popup_content_dev" data-oe-placeholder="' + _t("Type Here ...") + '"></div>'));
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @override
*/
_saveElement: function (outerHTML, recordInfo, editable) {
var self = this;
var defs = [this._super.apply(this, arguments)];
var $popups = $(editable).find('.o_newsletter_popup');
_.each($popups, function (popup) {
var $popup = $(popup);
var content = $popup.data('content');
if (content) {
defs.push(self._rpc({
route: '/website_mass_mailing/set_content',
params: {
'newsletter_id': parseInt($popup.attr('data-list-id')),
'content': content,
},
}));
}
var content = $('#wrapwrap .o_popup_content_dev').html();
var newsletter_id = $target.parent().attr('data-list-id');
ajax.jsonRpc('/web/dataset/call', 'call', {
model: 'mail.mass_mailing.list',
method: 'write',
args: [
parseInt(newsletter_id),
{'popup_content':content},
this.options.recordInfo.context,
],
});
}
return this._super.apply(this, arguments);
},
destroy: function () {
this.close_dialog();
this._super();
},
//--------------------------------------------------------------------------
// Handler
//--------------------------------------------------------------------------
close_dialog: function () {
$('#wrapwrap').find('#o_newsletter_popup').modal('hide');
},
edit_dialog: function (ev) {
$('#wrapwrap').find('#o_newsletter_popup').modal('show');
$('.o_popup_bounce_small').hide();
$('.modal-backdrop').css("z-index", "0");
});
return Promise.all(defs);
},
});
});
@@ -1,68 +1,89 @@
odoo.define('mass_mailing.website_integration', function (require) {
"use strict";
var config = require('web.config');
var core = require('web.core');
var Dialog = require('web.Dialog');
var utils = require('web.utils');
var publicWidget = require('web.public.widget');
var _t = core._t;
publicWidget.registry.subscribe = publicWidget.Widget.extend({
selector: ".js_subscribe",
disabledInEditableMode: false,
read_events: {
'click .js_subscribe_btn': '_onSubscribeClick',
},
/**
* @override
*/
start: function () {
var self = this;
var def = this._super.apply(this, arguments);
this.$popup = this.$target.closest('.o_newsletter_modal');
if (this.$popup.length) {
// No need to check whether the user subscribed or not if the input
// is in a popup as the popup won't open if he did subscribe.
return def;
}
var always = function (data) {
self.$target.find('input.js_subscribe_email')
.val(data.email ? data.email : "")
.attr("disabled", data.is_subscriber && data.email.length ? "disabled" : false);
self.$target.attr("data-subscribe", data.is_subscriber ? 'on' : 'off');
self.$target.find('a.js_subscribe_btn')
.attr("disabled", data.is_subscriber && data.email.length ? "disabled" : false);
var isSubscriber = data.is_subscriber;
self.$('.js_subscribe_btn').prop('disabled', isSubscriber);
self.$('input.js_subscribe_email')
.val(data.email || "")
.prop('disabled', isSubscriber);
self.$target.removeClass('d-none');
self.$target.find('.js_subscribe_btn').toggleClass('d-none', !!data.is_subscriber);
self.$target.find('.js_subscribed_btn').toggleClass('d-none', !data.is_subscriber);
self.$('.js_subscribe_btn').toggleClass('d-none', !!isSubscriber);
self.$('.js_subscribed_btn').toggleClass('d-none', !isSubscriber);
};
// set value and display button
self.$target.find("input").removeClass('d-none');
this._rpc({
return Promise.all([def, this._rpc({
route: '/website_mass_mailing/is_subscriber',
params: {
list_id: this.$target.data('list-id'),
'list_id': this.$target.data('list-id'),
},
}).then(always).guardedCatch(always);
// not if editable mode to allow designer to edit alert field
if (!this.editableMode) {
$('.js_subscribe > .alert').addClass('d-none');
$('.js_subscribe > .input-group-append.d-none').removeClass('d-none');
this.$target.find('.js_subscribe_btn').on('click', function (event) {
event.preventDefault();
self._onClick();
});
}
}).then(always).guardedCatch(always)]);
},
_onClick: function () {
/**
* @override
*/
destroy: function () {
this.$target.addClass('d-none');
this._super.apply(this, arguments);
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* @private
*/
_onSubscribeClick: function () {
var self = this;
var $email = this.$target.find(".js_subscribe_email:visible");
var $email = this.$(".js_subscribe_email:visible");
if ($email.length && !$email.val().match(/.+@.+/)) {
this.$target.addClass('o_has_error').find('.form-control, .custom-select').addClass('is-invalid');
this.$target.addClass('o_has_error').find('.form-control').addClass('is-invalid');
return false;
}
this.$target.removeClass('o_has_error').find('.form-control, .custom-select').removeClass('is-invalid');
this.$target.removeClass('o_has_error').find('.form-control').removeClass('is-invalid');
this._rpc({
route: '/website_mass_mailing/subscribe',
params: {
'list_id': this.$target.data('list-id'),
'email': $email.length ? $email.val() : false,
},
}).then(function (subscribe) {
self.$target.find(".js_subscribe_email, .input-group-append").addClass('d-none');
self.$target.find(".alert").removeClass('d-none');
self.$target.find('input.js_subscribe_email').attr("disabled", subscribe ? "disabled" : false);
self.$target.attr("data-subscribe", subscribe ? 'on' : 'off');
}).then(function (result) {
self.$(".js_subscribe_btn").addClass('d-none');
self.$(".js_subscribed_btn").removeClass('d-none');
self.$('input.js_subscribe_email').prop('disabled', !!result);
if (self.$popup.length) {
self.$popup.modal('hide');
}
self.displayNotification(_t("Success"), result.toast_content, 'success', true);
});
},
});
@@ -71,84 +92,106 @@ publicWidget.registry.newsletter_popup = publicWidget.Widget.extend({
selector: ".o_newsletter_popup",
disabledInEditableMode: false,
/**
* @override
*/
start: function () {
var self = this;
// Compatibility: rebuilding a correct modal from user database
// content. Since the first version, the modal is saved in databases
// directly but has never used a correct structure. While it was working
// with BS3, it is not with BS4.
// TODO review the newsletter popup creation, save and loading.
var $modal = this.$('.modal');
if ($modal.is('.modal-dialog')) {
$modal.removeClass('modal-md modal-dialog');
var $modalContent = $modal.find('.modal-content');
$modalContent.wrapAll($('<div/>', {class: 'modal-dialog'}));
var defs = [this._super.apply(this, arguments)];
this.websiteID = this._getContext().website_id;
this.listID = parseInt(this.$target.attr('data-list-id'));
if (!this.listID || (utils.get_cookie(_.str.sprintf("newsletter-popup-%s-%s", this.listID, this.websiteID)) && !self.editableMode)) {
return Promise.all(defs);
}
var popupcontent = self.$target.find(".o_popup_content_dev").empty();
if (!self.$target.data('list-id')) {
return;
}
this._rpc({
route: '/website_mass_mailing/get_content',
params: {
newsletter_id: self.$target.data('list-id'),
},
}).then(function (data) {
if (data.content) {
$('<div></div>').append(data.content).appendTo(popupcontent);
}
self.$target.find('input.popup_subscribe_email').val(data.email || "");
self.redirect_url = data.redirect_url;
if (!self.editableMode && !data.is_subscriber) {
$(document).on('mouseleave', _.bind(self.show_banner, self));
self.$target.find('.popup_subscribe_btn').on('click', function (event) {
event.preventDefault();
self._onClickSubscribe();
});
} else { $(document).off('mouseleave'); }
});
},
_onClickSubscribe: function () {
var self = this;
var $email = self.$target.find(".popup_subscribe_email:visible");
if ($email.length && !$email.val().match(/.+@.+/)) {
this.$target.addClass('o_has_error').find('.form-control, .custom-select').addClass('is-invalid');
return false;
}
this.$target.removeClass('o_has_error').find('.form-control, .custom-select').removeClass('is-invalid');
this._rpc({
route: '/website_mass_mailing/subscribe',
params: {
'list_id': self.$target.data('list-id'),
'email': $email.length ? $email.val() : false,
},
}).then(function (subscribe) {
self.$target.find('#o_newsletter_popup').modal('hide');
$(document).off('mouseleave');
if (self.redirect_url) {
if (_.contains(self.redirect_url.split('/'), window.location.host) || self.redirect_url.indexOf('/') === 0) {
window.location.href = self.redirect_url;
if (this.$target.data('content') && this.editableMode) {
// To avoid losing user changes.
this._dialogInit(this.$target.data('content'));
this.$target.removeData('quick-open');
this.massMailingPopup.open();
} else {
defs.push(this._rpc({
route: '/website_mass_mailing/get_content',
params: {
newsletter_id: self.listID,
},
}).then(function (data) {
self._dialogInit(data.popup_content, data.email || '');
if (!self.editableMode && !data.is_subscriber) {
if (config.device.isMobile) {
setTimeout(function () {
self._showBanner();
}, 5000);
} else {
$(document).on('mouseleave.open_popup_event', self._showBanner.bind(self));
}
} else {
window.open(self.redirect_url, '_blank');
$(document).off('mouseleave.open_popup_event');
}
// show popup after choosing a newsletter
if (self.$target.data('quick-open')) {
self.massMailingPopup.open();
self.$target.removeData('quick-open');
}
}));
}
return Promise.all(defs);
},
/**
* @override
*/
destroy: function () {
if (this.massMailingPopup) {
this.massMailingPopup.close();
}
this._super.apply(this, arguments);
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* @param {string} content
* @private
*/
_dialogInit: function (content, email) {
var self = this;
this.massMailingPopup = new Dialog(this, {
technical: false,
$content: $('<div/>').html(content),
$parentNode: this.$target,
backdrop: !this.editableMode,
dialogClass: 'p-0' + (this.editableMode ? ' o_editable oe_structure oe_empty' : ''),
renderFooter: false,
size: 'medium',
});
this.massMailingPopup.opened().then(function () {
var $modal = self.massMailingPopup.$modal;
$modal.addClass('o_newsletter_modal');
$modal.find('.oe_structure').attr('data-editor-message', _t('DRAG BUILDING BLOCKS HERE'));
$modal.find('.modal-dialog').addClass('modal-dialog-centered');
$modal.find('.js_subscribe').data('list-id', self.listID)
.find('input.js_subscribe_email').val(email);
self.trigger_up('widgets_start_request', {
editableMode: self.editableMode,
$target: $modal,
});
});
this.massMailingPopup.on('closed', this, function () {
var $modal = self.massMailingPopup.$modal;
if ($modal) { // The dialog might have never been opened
self.$el.data('content', $modal.find('.modal-body').html());
}
});
},
show_banner: function () {
var self = this;
if (!utils.get_cookie("newsletter-popup-"+ self.$target.data('list-id')) && self.$target) {
$('#o_newsletter_popup:first').modal('show').css({
'margin-top': '70px',
'position': 'fixed'
});
document.cookie = "newsletter-popup-"+ self.$target.data('list-id') +"=" + true + ";path=/";
}
}
/**
* @private
*/
_showBanner: function () {
this.massMailingPopup.open();
utils.set_cookie(_.str.sprintf("newsletter-popup-%s-%s", this.listID, this.websiteID), true);
$(document).off('mouseleave.open_popup_event');
},
});
});
@@ -0,0 +1,8 @@
.editor_enable {
.o_newsletter_modal {
// set z-index so customize options visible on dialog.
z-index: $o-wysiwyg-zindex - 2;
// just for fake backdrop effect
background-color: rgba(66, 66, 66, 0.4);
}
}
@@ -0,0 +1,23 @@
.o_newsletter_modal {
.modal-header {
padding: 0;
border: none;
}
.modal-title {
display: none;
}
.close {
@include o-position-absolute(0, 0);
font-size: $font-size-sm;
width: 2 * $font-size-sm;
height: 2 * $font-size-sm;
padding: 0;
margin: (-$font-size-sm) (-$font-size-sm) 0 0;
opacity: 1;
background-color: $white;
z-index: 1;
border-radius: $font-size-sm;
box-shadow: $box-shadow-sm;
}
}
@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="website_mass_mailing.edition.wrapper">
<div role="dialog" class="modal-dialog modal-md d-block" id="o_newsletter_popup">
<div class="modal-content o_popup_modal_content">
<div class="o_popup_modal_body text-center">
<div class="o_popup_content_dev">
<div id="wrapper"></div>
</div>
<div class="modal fade show d-block o_newsletter_modal">
<div role="dialog" class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<header>
<button type="button" class="close" aria-label="Close" tabindex="-1">×</button>
</header>
<div id="wrapper" class="modal-body oe_structure"></div>
</div>
</div>
</div>
@@ -1,26 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.ui.view" id="view_mail_mass_mailing_list_form">
<record id="view_mail_mass_mailing_list_form" model="ir.ui.view">
<field name="name">mail.mass_mailing.list.form</field>
<field name="model">mail.mass_mailing.list</field>
<field name="inherit_id" ref="mass_mailing.view_mail_mass_mailing_list_form"/>
<field name="arch" type="xml">
<xpath expr="//sheet" position="inside">
<notebook groups="website_mass_mailing.group_website_popup_on_exit">
<page string="Popup Content">
<field name="popup_content" widget="html" options="{
'snippets': 'website.snippets',
'cssEdit': 'website_mass_mailing.iframe_css_assets_edit',
'wrapper': 'website_mass_mailing.edition.wrapper',
}"/>
<notebook>
<page string="Website popups">
<field name="website_popup_ids">
<tree>
<field name="website_id"/>
</tree>
</field>
</page>
</notebook>
</xpath>
<xpath expr="//div[hasclass('oe_title')]" position="inside">
<group groups="website_mass_mailing.group_website_popup_on_exit">
<field name="popup_redirect_url"/>
<xpath expr="//div[hasclass('oe_title')]" position="after">
<group>
<field name="toast_content"/>
</group>
</xpath>
</field>
</record>
<record id="view_mail_mass_mailing_popup_form" model="ir.ui.view">
<field name="name">website.mass_mailing.popup.form</field>
<field name="model">website.mass_mailing.popup</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="mailing_list_id"/>
<field name="website_id" groups="website.group_multi_website"/>
</group>
<label for="popup_content"/>
<field name="popup_content" widget="html" options="{
'snippets': 'website.snippets',
'cssEdit': 'website_mass_mailing.iframe_css_assets_edit',
'wrapper': 'website_mass_mailing.edition.wrapper',
}"/>
</sheet>
</form>
</field>
</record>
</odoo>
@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="inherit_id" ref="mass_mailing.res_config_settings_view_form"/>
<field name="name">res.config.settings.view.form.inherit.website.mass.mailing</field>
<field name="model">res.config.settings</field>
<field name="arch" type="xml">
<xpath expr="//div[@id='mailing_list']" position="inside">
<div class="col-lg-6 o_setting_box col-12" title="This adds a new Newsletter Popup snippet to drag &amp; drop on your website pages. It triggers a popup when visitors land on the page. This popup prompts them to enter their email address to join a mailing list.">
<div class="o_setting_left_pane">
<field name="group_website_popup_on_exit"/>
</div>
<div class="o_setting_right_pane">
<label for="group_website_popup_on_exit"/>
<div class="text-muted">
Encourage to subscribe to mailing lists with a popup
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>
@@ -3,18 +3,18 @@
<template id="iframe_css_assets_edit" name="CSS assets for wysiwyg iframe content for popup">
<t t-call-assets="web.assets_common" t-js="false"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
<link rel="stylesheet" href="/website_mass_mailing/static/src/css/website_mass_mailing_popup.css" type="text/css"/>
</template>
<template id="remove_external_snippets" inherit_id="website.external_snippets">
<xpath expr="//t[@t-install='mass_mailing']" position="replace"/>
<xpath expr="//t[@id='newsletter_snippet']" position="replace"/>
<xpath expr="//t[@id='newsletter_popup_snippet']" position="replace"/>
<xpath expr="//t[@id='newsletter_block_snippet']" position="replace"/>
</template>
<template id="snippets" inherit_id="website.snippets">
<xpath expr="//div[@id='snippet_feature']//t[@t-snippet][last()]" position="after">
<t groups="website_mass_mailing.group_website_popup_on_exit">
<t t-snippet="website_mass_mailing.s_newsletter_subscribe_popup" t-thumbnail="/website_mass_mailing/static/src/img/blocks/newsletter_subscribe_popup.png"/>
</t>
<t t-snippet="website_mass_mailing.s_newsletter_subscribe_popup" t-thumbnail="/website/static/src/img/snippets_thumbs/newsletter_subscribe_popup.png"/>
<t t-snippet="website_mass_mailing.s_newsletter_block" t-thumbnail="/website/static/src/img/snippets_thumbs/s_newsletter_block.png"/>
</xpath>
<xpath expr="//div[@id='snippet_content']//t[@t-snippet][last()]" position="after">
@@ -23,35 +23,35 @@
</template>
<template id="s_newsletter_subscribe_form" name="Newsletter">
<div class="oe_snippet_body input-group js_subscribe" data-list-id="0">
<div class="input-group js_subscribe" data-list-id="0">
<input type="email" name="email" class="js_subscribe_email form-control" placeholder="your email..."/>
<span class="input-group-append">
<a role="button" href="#" class="btn btn-primary js_subscribe_btn">Subscribe</a>
<a role="button" href="#" class="btn btn-success js_subscribed_btn d-none" disabled="disabled">Thanks</a>
</span>
<div class="alert alert-success d-none" role="status">Thanks for your subscription!</div>
</div>
</template>
<template id="s_newsletter_block" name="Newsletter block">
<section class="s_newsletter_block pt64 pb64 oe_img_bg oe_custom_bg" style="background-image: url('/web/image/website.library_image_17');">
<div class="container">
<div class="row">
<div class="col-lg-7 offset-lg-5 pt32 pb32 bg-white-75">
<div class="text-center">
<h1 class="text-uppercase font-weight-bold">Always First.</h1>
<p>Be the first to find out all the latest news, products and trends.</p>
<t t-call="website_mass_mailing.s_newsletter_subscribe_form"/>
</div>
</div>
</div>
</div>
</section>
</template>
<template id="s_newsletter_subscribe_popup" name="Newsletter Popup">
<div class="o_newsletter_popup" data-list-id="0">
<div class="alert alert-warning alert-dismissible fade show css_non_editable_mode_hidden o_not_editable" role="status">
<strong>Newsletter Popup!</strong> The newsletter popup snippet effect is active on this page. Click <a id="edit_dialog" href="#">Here To Edit Dialog Content</a>
</div>
<div role="dialog" class="modal modal-dialog modal-md fade-custom" id="o_newsletter_popup" tabindex="-1">
<div class="modal-content o_popup_modal_content">
<a role="button" href="#" class="o_popup_btn_close o_not_editable" data-dismiss="modal">&amp;times;</a>
<div class="o_popup_modal_body text-center">
<div class="o_popup_content_dev" data-oe-placeholder="Type Here ..."/>
<div class="input-group o_not_editable o_popup_animated o_popup_bounce_del500ms o_popup_bounce_small" >
<input type="email" name="email" class="popup_subscribe_email form-control" placeholder="your email..." autofocus="autofocus"/>
<div class="input-group-append">
<a role="button" href="#" class="btn btn-success popup_subscribe_btn">Subscribe</a>
</div>
</div>
</div>
</div>
<div class="alert alert-warning css_non_editable_mode_hidden o_not_editable" role="alert">
<strong>Newsletter Popup!</strong> The newsletter popup is active on this page. <a class="o_edit_popup" data-toggle="modal" href="#">Edit Popup</a>
</div>
</div>
</template>
@@ -60,12 +60,17 @@
<xpath expr="//*[@id='so_snippet_addition']" position="attributes">
<attribute name="data-selector" add=".o_newsletter_popup" separator=","/>
</xpath>
<xpath expr="//*[@id='row_valign_snippet_option']" position="attributes">
<attribute name="data-selector" separator="," add=".s_newsletter_block"/>
</xpath>
<xpath expr="//div" position="after">
<t t-set="selector" t-value="'.js_subscribe'"/>
<div data-js="mailing_list_subscribe"
data-selector=".js_subscribe"
data-drop-near="p, h1, h2, h3, blockquote, .card">
t-att-data-selector="selector"
t-attf-data-exclude=".o_newsletter_modal #{selector}">
<a tabindex="-1" href="#" class="dropdown-item" data-select_mailing_list="" data-no-preview="true">Change Newsletter</a>
</div>
<div t-att-data-selector="selector" data-drop-near="p, h1, h2, h3, blockquote, .card"/>
<div data-js="newsletter_popup"
data-selector=".o_newsletter_popup">
<a tabindex="-1" href="#" class="dropdown-item" data-select_mailing_list="" data-no-preview="true">Change Newsletter</a>
@@ -148,4 +153,5 @@
</td>
</xpath>
</template>
</odoo>
@@ -3,7 +3,7 @@
<template id="assets_frontend" inherit_id="website.assets_frontend">
<xpath expr="//link[last()]" position="after">
<link rel="stylesheet" href="/website_mass_mailing/static/src/css/website_mass_mailing_popup.css" type="text/css"/>
<link rel="stylesheet" type="text/scss" href="/website_mass_mailing/static/src/scss/website_mass_mailing_popup.scss"/>
</xpath>
<xpath expr="//script[last()]" position="after">
<script type="text/javascript" src="/website_mass_mailing/static/src/js/website_mass_mailing.js"/>
@@ -11,6 +11,9 @@
</template>
<template id="assets_editor" inherit_id="website.assets_editor">
<xpath expr="//link[last()]" position="after">
<link rel="stylesheet" type="text/scss" href="/website_mass_mailing/static/src/scss/website_mass_mailing.editor.scss"/>
</xpath>
<xpath expr="//script[last()]" position="after">
<script type="text/javascript" src="/website_mass_mailing/static/src/js/website_mass_mailing.editor.js"/>
</xpath>