[MIG] mass_mailing_custom_unsubscribe: Migration to 14.0

This commit is contained in:
Ernesto Tejeda 2021-07-21 16:53:13 -04:00
parent 8ff3bdb743
commit 9b7ef0ae19
11 changed files with 201 additions and 309 deletions

View File

@ -14,13 +14,13 @@ Customizable unsubscription process on mass mailing emails
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3 :alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github
:target: https://github.com/OCA/social/tree/13.0/mass_mailing_custom_unsubscribe :target: https://github.com/OCA/social/tree/14.0/mass_mailing_custom_unsubscribe
:alt: OCA/social :alt: OCA/social
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/social-13-0/social-13-0-mass_mailing_custom_unsubscribe :target: https://translation.odoo-community.org/projects/social-14-0/social-14-0-mass_mailing_custom_unsubscribe
:alt: Translate me on Weblate :alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png .. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
:target: https://runbot.odoo-community.org/runbot/205/13.0 :target: https://runbot.odoo-community.org/runbot/205/14.0
:alt: Try me on Runbot :alt: Try me on Runbot
|badge1| |badge2| |badge3| |badge4| |badge5| |badge1| |badge2| |badge3| |badge4| |badge5|
@ -88,7 +88,7 @@ Bug Tracker
Bugs are tracked on `GitHub Issues <https://github.com/OCA/social/issues>`_. Bugs are tracked on `GitHub Issues <https://github.com/OCA/social/issues>`_.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/social/issues/new?body=module:%20mass_mailing_custom_unsubscribe%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_. `feedback <https://github.com/OCA/social/issues/new?body=module:%20mass_mailing_custom_unsubscribe%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues. Do not contact contributors directly about support or help with technical issues.
@ -126,6 +126,6 @@ OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and mission is to support the collaborative development of Odoo features and
promote its widespread use. promote its widespread use.
This module is part of the `OCA/social <https://github.com/OCA/social/tree/13.0/mass_mailing_custom_unsubscribe>`_ project on GitHub. This module is part of the `OCA/social <https://github.com/OCA/social/tree/14.0/mass_mailing_custom_unsubscribe>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@ -6,7 +6,7 @@
"name": "Customizable unsubscription process on mass mailing emails", "name": "Customizable unsubscription process on mass mailing emails",
"summary": "Know and track (un)subscription reasons, GDPR compliant", "summary": "Know and track (un)subscription reasons, GDPR compliant",
"category": "Marketing", "category": "Marketing",
"version": "13.0.2.0.0", "version": "14.0.1.0.0",
"depends": ["mass_mailing"], "depends": ["mass_mailing"],
"data": [ "data": [
"security/ir.model.access.csv", "security/ir.model.access.csv",
@ -20,7 +20,7 @@
], ],
"demo": ["demo/assets.xml"], "demo": ["demo/assets.xml"],
"images": ["images/form.png"], "images": ["images/form.png"],
"author": "Tecnativa," "Odoo Community Association (OCA)", "author": "Tecnativa, Odoo Community Association (OCA)",
"website": "https://github.com/OCA/social", "website": "https://github.com/OCA/social",
"license": "AGPL-3", "license": "AGPL-3",
"installable": True, "installable": True,

View File

@ -4,7 +4,7 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 13.0\n" "Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
@ -47,11 +47,17 @@ msgstr ""
#: code:addons/mass_mailing_custom_unsubscribe/static/src/js/unsubscribe.js:0 #: code:addons/mass_mailing_custom_unsubscribe/static/src/js/unsubscribe.js:0
#: code:addons/mass_mailing_custom_unsubscribe/static/src/js/unsubscribe.js:0 #: code:addons/mass_mailing_custom_unsubscribe/static/src/js/unsubscribe.js:0
#: code:addons/mass_mailing_custom_unsubscribe/static/src/js/unsubscribe.js:0 #: code:addons/mass_mailing_custom_unsubscribe/static/src/js/unsubscribe.js:0
#, python-format
msgid "An error occured. Please try again later or contact us."
msgstr ""
#. module: mass_mailing_custom_unsubscribe
#. openerp-web
#: code:addons/mass_mailing_custom_unsubscribe/static/src/js/unsubscribe.js:0 #: code:addons/mass_mailing_custom_unsubscribe/static/src/js/unsubscribe.js:0
#: code:addons/mass_mailing_custom_unsubscribe/static/src/js/unsubscribe.js:0 #: code:addons/mass_mailing_custom_unsubscribe/static/src/js/unsubscribe.js:0
#: code:addons/mass_mailing_custom_unsubscribe/static/src/js/unsubscribe.js:0 #: code:addons/mass_mailing_custom_unsubscribe/static/src/js/unsubscribe.js:0
#, python-format #, python-format
msgid "An error occured. Please try again later or contact us." msgid "An error occurred. Please try again later or contact us."
msgstr "" msgstr ""
#. module: mass_mailing_custom_unsubscribe #. module: mass_mailing_custom_unsubscribe
@ -112,8 +118,11 @@ msgid "Details Required"
msgstr "" msgstr ""
#. module: mass_mailing_custom_unsubscribe #. module: mass_mailing_custom_unsubscribe
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_blacklist__display_name
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_unsubscription__display_name #: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_unsubscription__display_name
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_unsubscription_reason__display_name #: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_unsubscription_reason__display_name
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mailing_list__display_name
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mailing_mailing__display_name
msgid "Display Name" msgid "Display Name"
msgstr "" msgstr ""
@ -169,8 +178,11 @@ msgid "I'm not interested"
msgstr "" msgstr ""
#. module: mass_mailing_custom_unsubscribe #. module: mass_mailing_custom_unsubscribe
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_blacklist__id
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_unsubscription__id #: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_unsubscription__id
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_unsubscription_reason__id #: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_unsubscription_reason__id
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mailing_list__id
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mailing_mailing__id
msgid "ID" msgid "ID"
msgstr "" msgstr ""
@ -200,8 +212,11 @@ msgid "Is Follower"
msgstr "" msgstr ""
#. module: mass_mailing_custom_unsubscribe #. module: mass_mailing_custom_unsubscribe
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_blacklist____last_update
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_unsubscription____last_update #: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_unsubscription____last_update
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_unsubscription_reason____last_update #: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mail_unsubscription_reason____last_update
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mailing_list____last_update
#: model:ir.model.fields,field_description:mass_mailing_custom_unsubscribe.field_mailing_mailing____last_update
msgid "Last Modified on" msgid "Last Modified on"
msgstr "" msgstr ""

View File

@ -1,17 +0,0 @@
# Copyright 2021 Tecnativa - David Vidal
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
from openupgradelib import openupgrade
@openupgrade.migrate()
def migrate(env, version):
openupgrade.logged_query(
env.cr,
"""
UPDATE mail_unsubscription
SET unsubscriber_id = replace(
unsubscriber_id, 'mail.mass_mailing.contact', 'mailing.contact'
)
WHERE unsubscriber_id LIKE 'mail.mass_mailing_contact%'
""",
)

View File

@ -367,7 +367,7 @@ ul.auto-toc {
!! This file is generated by oca-gen-addon-readme !! !! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !! !! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/social/tree/13.0/mass_mailing_custom_unsubscribe"><img alt="OCA/social" src="https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/social-13-0/social-13-0-mass_mailing_custom_unsubscribe"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/205/13.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p> <p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/OCA/social/tree/14.0/mass_mailing_custom_unsubscribe"><img alt="OCA/social" src="https://img.shields.io/badge/github-OCA%2Fsocial-lightgray.png?logo=github" /></a> <a class="reference external" href="https://translation.odoo-community.org/projects/social-14-0/social-14-0-mass_mailing_custom_unsubscribe"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external" href="https://runbot.odoo-community.org/runbot/205/14.0"><img alt="Try me on Runbot" src="https://img.shields.io/badge/runbot-Try%20me-875A7B.png" /></a></p>
<p>This addon extends the unsubscription form to let you:</p> <p>This addon extends the unsubscription form to let you:</p>
<ul class="simple"> <ul class="simple">
<li>Choose which mailing lists are not cross-unsubscriptable when unsubscribing <li>Choose which mailing lists are not cross-unsubscriptable when unsubscribing
@ -440,7 +440,7 @@ duplicated functionality and depending on it instead of replacing it).</li>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/social/issues">GitHub Issues</a>. <p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/social/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported. In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/OCA/social/issues/new?body=module:%20mass_mailing_custom_unsubscribe%0Aversion:%2013.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p> <a class="reference external" href="https://github.com/OCA/social/issues/new?body=module:%20mass_mailing_custom_unsubscribe%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p> <p>Do not contact contributors directly about support or help with technical issues.</p>
</div> </div>
<div class="section" id="credits"> <div class="section" id="credits">
@ -473,7 +473,7 @@ If you spotted it first, help us smashing it by providing a detailed and welcome
<p>OCA, or the Odoo Community Association, is a nonprofit organization whose <p>OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and mission is to support the collaborative development of Odoo features and
promote its widespread use.</p> promote its widespread use.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/social/tree/13.0/mass_mailing_custom_unsubscribe">OCA/social</a> project on GitHub.</p> <p>This module is part of the <a class="reference external" href="https://github.com/OCA/social/tree/14.0/mass_mailing_custom_unsubscribe">OCA/social</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p> <p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div> </div>
</div> </div>

View File

@ -1,15 +1,13 @@
/* Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com> /* Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */ * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
odoo.define("mass_mailing_custom_unsubscribe.contact_tour", function (require) { odoo.define("mass_mailing_custom_unsubscribe.contact_tour", (require) => {
"use strict"; "use strict";
var base = require("web_editor.base"); const base = require("web_editor.base");
var tour = require("web_tour.tour"); const tour = require("web_tour.tour");
// Allow to know if an element is required // Allow to know if an element is required
$.extend($.expr[":"], { $.extend($.expr[":"], {
propRequired: function (element) { propRequired: (element) => $(element).prop("required"),
return $(element).prop("required");
},
}); });
tour.register( tour.register(
@ -59,8 +57,7 @@ odoo.define("mass_mailing_custom_unsubscribe.contact_tour", function (require) {
{ {
content: "Choose other reason", content: "Choose other reason",
trigger: ".radio:contains('Other reason') :radio", trigger: ".radio:contains('Other reason') :radio",
extra_trigger: extra_trigger: ".radio:contains('Other reason') :radio:not(:checked)",
".radio:contains('Other reason') " + ":radio:not(:checked)",
}, },
{ {
content: "Add details to reason", content: "Add details to reason",
@ -78,18 +75,13 @@ odoo.define("mass_mailing_custom_unsubscribe.contact_tour", function (require) {
}, },
{ {
content: "Subscribe again to list 0", content: "Subscribe again to list 0",
// eslint-disable-next-line no-multi-str
trigger: trigger:
"body:not(:has(#unsubscribe_form #custom_div_feedback\ "body:not(:has(#unsubscribe_form #custom_div_feedback:visible)):has(.alert-success) li:contains('test list 0') input:not(:checked)",
:visible)):has(.alert-success) li:contains('test list 0') \
input:not(:checked)",
}, },
{ {
content: "Update subscriptions 3nd time", content: "Update subscriptions 3nd time",
// eslint-disable-next-line no-multi-str
trigger: trigger:
"#unsubscribe_form:not(\ "#unsubscribe_form:not(:has(.js_unsubscription_reason:visible)) :submit",
:has(.js_unsubscription_reason:visible)) :submit",
}, },
{ {
content: "Successfully subscribed", content: "Successfully subscribed",

View File

@ -1,15 +1,13 @@
/* Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com> /* Copyright 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */ * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
odoo.define("mass_mailing_custom_unsubscribe.partner_tour", function (require) { odoo.define("mass_mailing_custom_unsubscribe.partner_tour", (require) => {
"use strict"; "use strict";
var base = require("web_editor.base"); const base = require("web_editor.base");
var tour = require("web_tour.tour"); const tour = require("web_tour.tour");
// Allow to know if an element is required // Allow to know if an element is required
$.extend($.expr[":"], { $.extend($.expr[":"], {
propRequired: function (element) { propRequired: (element) => $(element).prop("required"),
return $(element).prop("required");
},
}); });
tour.register( tour.register(
@ -26,10 +24,7 @@ odoo.define("mass_mailing_custom_unsubscribe.partner_tour", function (require) {
}, },
{ {
content: "Switch to not interested reason", content: "Switch to not interested reason",
// eslint-disable-next-line no-multi-str trigger: '.radio:contains("I\'m not interested") :radio:not(:checked)',
trigger:
'.radio:contains("I\'m not interested") \
:radio:not(:checked)',
extra_trigger: "[name='details']:propRequired", extra_trigger: "[name='details']:propRequired",
}, },
{ {

View File

@ -3,35 +3,37 @@
/* This JS module replaces core AJAX submission because it is impossible /* This JS module replaces core AJAX submission because it is impossible
* to extend it as it is currently designed. It is almost a copy+paste from * to extend it as it is currently designed. It is almost a copy+paste from
* upstream, to allow easier version/patch updates, so linter is disabled. */ * upstream, to allow easier version/patch updates, so linter is disabled
* and prettier is ignore. */
/* eslint-disable */ /* eslint-disable */
// prettier-ignore
odoo.define("mass_mailing_custom_unsubscribe.unsubscribe", function (require) { odoo.define("mass_mailing_custom_unsubscribe.unsubscribe", function (require) {
"use strict"; "use strict";
var ajax = require("web.ajax"); var session = require('web.session');
var core = require("web.core"); var ajax = require('web.ajax');
require("web.dom_ready"); var core = require('web.core');
require('web.dom_ready');
var _t = core._t; var _t = core._t;
if (!$(".o_unsubscribe_form").length) {
return $.Deferred().reject("DOM doesn't contain '.o_unsubscribe_form'");
}
var email = $("input[name='email']").val(); var email = $("input[name='email']").val();
var mailing_id = parseInt($("input[name='mailing_id']").val(), 10); var mailing_id = parseInt($("input[name='mailing_id']").val(), 10);
var res_id = parseInt($("input[name='res_id']").val(), 10); var res_id = parseInt($("input[name='res_id']").val(), 10);
var token = (location.search.split("token" + "=")[1] || "").split("&")[0]; var token = (location.search.split('token' + '=')[1] || '').split('&')[0];
var $mailing_lists = $("input[name='contact_ids']"); var $mailing_lists = $("input[name='contact_ids']");
var $reasons = $("#custom_div_feedback"); var $reasons = $("#custom_div_feedback");
var $details = $("textarea[name='details']"); var $details = $("textarea[name='details']");
var $radio = $(":radio"); var $radio = $(":radio");
var $info_state = $("#info_state, #custom_div_feedback"); var $info_state = $("#info_state, #custom_div_feedback");
$radio.on("change click", function (e) { if (!$('.o_unsubscribe_form').length) {
return Promise.reject("DOM doesn't contain '.o_unsubscribe_form'");
}
$radio.on('change click', function (e) {
$details.prop( $details.prop(
"required", 'required',
$(e.target).is("[data-details-required]") && $(e.target).is(":visible") $(e.target).is('[data-details-required]') && $(e.target).is(':visible')
); );
}); });
@ -40,99 +42,84 @@ odoo.define("mass_mailing_custom_unsubscribe.unsubscribe", function (require) {
// Find contacts that were checked and now are unchecked // Find contacts that were checked and now are unchecked
var $disabled = $mailing_lists.filter(function () { var $disabled = $mailing_lists.filter(function () {
var $this = $(this); var $this = $(this);
return !$this.prop("checked") && $this.attr("checked"); return !$this.prop('checked') && $this.attr('checked');
}); });
// Hide reasons form if you are only subscribing // Hide reasons form if you are only subscribing
$reasons.toggleClass("d-none", !$disabled.length); $reasons.toggleClass('d-none', !$disabled.length);
var $radios = $reasons.find(":radio"); var $radios = $reasons.find(':radio');
if ($reasons.is(":hidden")) { if ($reasons.is(':hidden')) {
// Uncheck chosen reason // Uncheck chosen reason
$radios $radios
.prop("checked", false) .prop('checked', false)
// Unrequire specifying a reason // Unrequire specifying a reason
.prop("required", false) .prop('required', false)
// Remove possible constraints for details // Remove possible constraints for details
.trigger("change"); .trigger('change');
// Clear textarea // Clear textarea
$details.val(""); $details.val('');
} else { } else {
// Require specifying a reason // Require specifying a reason
$radios.prop("required", true); $radios.prop('required', true);
} }
}; };
$mailing_lists.change(function (e) { $mailing_lists.change(function (e) {
toggle_reasons(); toggle_reasons();
$("#info_state").addClass("invisible"); $('#info_state').addClass('invisible');
}); });
if (email != "" && email != undefined) { session.load_translations().then(function () {
ajax.jsonRpc("/mailing/blacklist/check", "call", { if (email != '' && email != undefined){
email: email, ajax.jsonRpc('/mailing/blacklist/check', 'call', {'email': email, 'mailing_id': mailing_id, 'res_id': res_id, 'token': token})
mailing_id: mailing_id, .then(function (result) {
res_id: res_id, if (result == 'unauthorized'){
token: token, $('#button_add_blacklist').hide();
}) $('#button_remove_blacklist').hide();
.then(function (result) { }
if (result == "unauthorized") { else if (result == true) {
$("#button_add_blacklist").hide(); $('#button_remove_blacklist').show();
$("#button_remove_blacklist").hide(); toggle_opt_out_section(false);
} else if (result == true) { }
$("#button_remove_blacklist").show(); else if (result == false) {
toggle_opt_out_section(false); $('#button_add_blacklist').show();
} else if (result == false) { toggle_opt_out_section(true);
$("#button_add_blacklist").show(); }
toggle_opt_out_section(true); else {
} else { $('#subscription_info').html(_t('An error occurred. Please try again later or contact us.'));
$("#subscription_info").html( $info_state.removeClass('alert-success').removeClass('alert-info').removeClass('alert-warning').addClass('alert-error');
_t("An error occured. Please try again later or contact us.") }
); })
$info_state .guardedCatch(function () {
.removeClass("alert-success") $('#subscription_info').html(_t('An error occurred. Please try again later or contact us.'));
.removeClass("alert-info") $info_state.removeClass('alert-success').removeClass('alert-info').removeClass('alert-warning').addClass('alert-error');
.removeClass("alert-warning") });
.addClass("alert-error"); }
} else {
}) $('#div_blacklist').hide();
.guardedCatch(function () { }
$("#subscription_info").html(
_t("An error occured. Please try again later or contact us.")
);
$info_state
.removeClass("alert-success")
.removeClass("alert-info")
.removeClass("alert-warning")
.addClass("alert-error");
});
} else {
$("#div_blacklist").hide();
}
var unsubscribed_list = $("input[name='unsubscribed_list']").val(); var unsubscribed_list = $("input[name='unsubscribed_list']").val();
if (unsubscribed_list) { if (unsubscribed_list){
$("#subscription_info").html( $('#subscription_info').html(_.str.sprintf(
_.str.sprintf(
_t("You have been <strong>successfully unsubscribed from %s</strong>."), _t("You have been <strong>successfully unsubscribed from %s</strong>."),
unsubscribed_list _.escape(unsubscribed_list)
) ));
); }
} else { else{
$("#subscription_info").html( $('#subscription_info').html(_t('You have been <strong>successfully unsubscribed</strong>.'));
_t("You have been <strong>successfully unsubscribed</strong>.") }
); });
}
$("#unsubscribe_form").on("submit", function (e) { $('#unsubscribe_form').on('submit', function (e) {
e.preventDefault(); e.preventDefault();
var checked_ids = []; var checked_ids = [];
$("input[type='checkbox']:checked").each(function (i) { $("input[type='checkbox']:checked").each(function (i) {
checked_ids[i] = parseInt($(this).val(), 10); checked_ids[i] = parseInt($(this).val(), 10);
}); });
var unchecked_ids = []; var unchecked_ids = [];
$("input[type='checkbox']:not(:checked)").each(function (i) { $("input[type='checkbox']:not(:checked)").each(function (i) {
unchecked_ids[i] = parseInt($(this).val(), 10); unchecked_ids[i] = parseInt($(this).val(), 10);
}); });
var values = { var values = {
@ -144,222 +131,144 @@ odoo.define("mass_mailing_custom_unsubscribe.unsubscribe", function (require) {
token: token, token: token,
}; };
// Only send reason and details if an unsubscription was found // Only send reason and details if an unsubscription was found
if ($reasons.is(":visible")) { if ($reasons.is(':visible')) {
values.reason_id = parseInt( values.reason_id = parseInt(
$reasons.find("[name='reason_id']:checked").val(), $reasons.find("[name='reason_id']:checked").val(), 10
10
); );
values.details = $details.val(); values.details = $details.val();
} }
ajax.jsonRpc("/mail/mailing/unsubscribe", "call", values) ajax.jsonRpc('/mail/mailing/unsubscribe', 'call', values)
.then(function (result) { .then(function (result) {
if (result == "unauthorized") { if (result == 'unauthorized'){
$("#info_state").removeClass("invisible"); $('#subscription_info').html(_t('You are not authorized to do this!'));
$("#subscription_info").html( $('#info_state').removeClass('invisible');
_t("You are not authorized to do this!") $info_state.removeClass('alert-success').removeClass('alert-info').removeClass('alert-error').addClass('alert-warning');
); }
$info_state else if (result == true) {
.removeClass("alert-success") $('#subscription_info').html(_t('Your changes have been saved.'));
.removeClass("alert-info") $('#info_state').removeClass('invisible');
.removeClass("alert-error") $info_state.removeClass('alert-info').addClass('alert-success');
.addClass("alert-warning");
} else if (result == true) {
$("#info_state").removeClass("invisible");
$("#subscription_info").html(_t("Your changes have been saved."));
$info_state.removeClass("alert-info").addClass("alert-success");
// Store checked status, to enable further changes // Store checked status, to enable further changes
$mailing_lists.each(function () { $mailing_lists.each(function () {
var $this = $(this); var $this = $(this);
$this.attr("checked", $this.prop("checked")); $this.attr('checked', $this.prop('checked'));
}); });
toggle_reasons(); toggle_reasons();
} else { }
$("#info_state").removeClass("invisible"); else {
$("#subscription_info").html( $('#subscription_info').html(_t('An error occurred. Your changes have not been saved, try again later.'));
_t( $('#info_state').removeClass('invisible');
"An error occurred. Your changes have not been saved, try again later." $info_state.removeClass('alert-info').addClass('alert-warning');
)
);
$info_state.removeClass("alert-info").addClass("alert-warning");
} }
}) })
.guardedCatch(function () { .guardedCatch(function () {
$("#info_state").removeClass("invisible"); $('#subscription_info').html(_t('An error occurred. Your changes have not been saved, try again later.'));
$("#subscription_info").html( $('#info_state').removeClass('invisible');
_t( $info_state.removeClass('alert-info').addClass('alert-warning');
"An error occurred. Your changes have not been saved, try again later."
)
);
$info_state.removeClass("alert-info").addClass("alert-warning");
}); });
}); });
// ================== // ==================
// Blacklist // Blacklist
// ================== // ==================
$("#button_add_blacklist").click(function (e) { $('#button_add_blacklist').click(function (e) {
e.preventDefault(); e.preventDefault();
if ($reasons.is(":hidden")) { if ($reasons.is(':hidden')) {
$reasons.toggleClass("d-none", false); $reasons.toggleClass('d-none', false);
$reasons.find(":radio").prop("required", true); $reasons.find(':radio').prop('required', true);
} }
if (!$("#unsubscribe_form")[0].reportValidity()) { if (!$('#unsubscribe_form')[0].reportValidity()) {
return; return;
} }
ajax.jsonRpc("/mailing/blacklist/add", "call", { ajax.jsonRpc('/mailing/blacklist/add', 'call', {'email': email, 'mailing_id': mailing_id, 'res_id': res_id, 'token': token,
email: email, 'reason_id': parseInt($reasons.find("[name='reason_id']:checked").val(), 10),
mailing_id: mailing_id, 'details': $details.val(),
res_id: res_id,
token: token,
reason_id: parseInt($reasons.find("[name='reason_id']:checked").val(), 10),
details: $details.val(),
}) })
.then(function (result) { .then(function (result) {
if (result == "unauthorized") { if (result == 'unauthorized'){
$("#info_state").removeClass("invisible"); $('#subscription_info').html(_t('You are not authorized to do this!'));
$("#subscription_info").html( $('#info_state').removeClass('invisible');
_t("You are not authorized to do this!") $info_state.removeClass('alert-success').removeClass('alert-info').removeClass('alert-error').addClass('alert-warning');
); }
$info_state else
.removeClass("alert-success") {
.removeClass("alert-info")
.removeClass("alert-error")
.addClass("alert-warning");
} else {
if (result) { if (result) {
$("#info_state").removeClass("invisible"); $('#subscription_info').html(_t('You have been successfully <strong>added to our blacklist</strong>. '
$("#subscription_info").html( + 'You will not be contacted anymore by our services.'));
_t( $('#info_state').removeClass('invisible');
"You have been successfully <strong>added to our blacklist</strong>. " + $info_state.removeClass('alert-warning').removeClass('alert-info').removeClass('alert-error').addClass('alert-success');
"You will not be contacted anymore by our services."
)
);
$info_state
.removeClass("alert-warning")
.removeClass("alert-info")
.removeClass("alert-error")
.addClass("alert-success");
toggle_opt_out_section(false); toggle_opt_out_section(false);
// set mailing lists checkboxes to previous state // set mailing lists checkboxes to previous state
$mailing_lists.each(function () { $mailing_lists.each(function () {
var $this = $(this); var $this = $(this);
$this.prop("checked", $(this)[0].hasAttribute("checked")); $this.prop('checked', $(this)[0].hasAttribute('checked'));
}); });
// Hide reasons and reset reason fields // Hide reasons and reset reason fields
$reasons $reasons.toggleClass('d-none', true).find(':radio').prop('checked', false);
.toggleClass("d-none", true) $details.val('').prop('required', false);
.find(":radio")
.prop("checked", false);
$details.val("").prop("required", false);
} else {
$("#info_state").removeClass("invisible");
$("#subscription_info").html(
_t(
"An error occured. Please try again later or contact us."
)
);
$info_state
.removeClass("alert-success")
.removeClass("alert-info")
.removeClass("alert-warning")
.addClass("alert-error");
} }
$("#button_add_blacklist").hide(); else {
$("#button_remove_blacklist").show(); $('#subscription_info').html(_t('An error occurred. Please try again later or contact us.'));
$("#unsubscribed_info").hide(); $('#info_state').removeClass('invisible');
$info_state.removeClass('alert-success').removeClass('alert-info').removeClass('alert-warning').addClass('alert-error');
}
$('#button_add_blacklist').hide();
$('#button_remove_blacklist').show();
$('#unsubscribed_info').hide();
} }
}) })
.guardedCatch(function () { .guardedCatch(function () {
$("#subscription_info").html( $('#subscription_info').html(_t('An error occured. Please try again later or contact us.'));
_t("An error occured. Please try again later or contact us.") $info_state.removeClass('alert-success').removeClass('alert-info').removeClass('alert-warning').addClass('alert-error');
);
$info_state
.removeClass("alert-success")
.removeClass("alert-info")
.removeClass("alert-warning")
.addClass("alert-error");
}); });
}); });
$("#button_remove_blacklist").click(function (e) { $('#button_remove_blacklist').click(function (e) {
e.preventDefault(); e.preventDefault();
ajax.jsonRpc("/mailing/blacklist/remove", "call", { ajax.jsonRpc('/mailing/blacklist/remove', 'call', {'email': email, 'mailing_id': mailing_id, 'res_id': res_id, 'token': token})
email: email,
mailing_id: mailing_id,
res_id: res_id,
token: token,
})
.then(function (result) { .then(function (result) {
if (result == "unauthorized") { if (result == 'unauthorized'){
$("#info_state").removeClass("invisible"); $('#subscription_info').html(_t('You are not authorized to do this!'));
$("#subscription_info").html( $('#info_state').removeClass('invisible');
_t("You are not authorized to do this!") $info_state.removeClass('alert-success').removeClass('alert-info').removeClass('alert-error').addClass('alert-warning');
); }
$info_state else
.removeClass("alert-success") {
.removeClass("alert-info")
.removeClass("alert-error")
.addClass("alert-warning");
} else {
if (result) { if (result) {
$("#info_state").removeClass("invisible"); $('#subscription_info').html(_t("You have been successfully <strong>removed from our blacklist</strong>. "
$("#subscription_info").html( + "You are now able to be contacted by our services."));
_t( $('#info_state').removeClass('invisible');
"You have been successfully <strong>removed from our blacklist</strong>. " + $info_state.removeClass('alert-warning').removeClass('alert-info').removeClass('alert-error').addClass('alert-success');
"You are now able to be contacted by our services."
)
);
$info_state
.removeClass("alert-warning")
.removeClass("alert-info")
.removeClass("alert-error")
.addClass("alert-success");
toggle_opt_out_section(true); toggle_opt_out_section(true);
} else {
$("#info_state").removeClass("invisible");
$("#subscription_info").html(
_t(
"An error occured. Please try again later or contact us."
)
);
$info_state
.removeClass("alert-success")
.removeClass("alert-info")
.removeClass("alert-warning")
.addClass("alert-error");
} }
$("#button_add_blacklist").show(); else {
$("#button_remove_blacklist").hide(); $('#subscription_info').html(_t('An error occured. Please try again later or contact us.'));
$("#unsubscribed_info").hide(); $('#info_state').removeClass('invisible');
$info_state.removeClass('alert-success').removeClass('alert-info').removeClass('alert-warning').addClass('alert-error');
}
$('#button_add_blacklist').show();
$('#button_remove_blacklist').hide();
$('#unsubscribed_info').hide();
} }
}) })
.guardedCatch(function () { .guardedCatch(function () {
$("#info_state").removeClass("invisible"); $('#subscription_info').html(_t('An error occured. Please try again later or contact us.'));
$("#subscription_info").html( $('#info_state').removeClass('invisible');
_t("An error occured. Please try again later or contact us.") $info_state.removeClass('alert-success').removeClass('alert-info').removeClass('alert-warning').addClass('alert-error');
);
$info_state
.removeClass("alert-success")
.removeClass("alert-info")
.removeClass("alert-warning")
.addClass("alert-error");
}); });
}); });
}); });
// prettier-ignore
function toggle_opt_out_section(value) { function toggle_opt_out_section(value) {
var result = !value; var result = !value;
$("#div_opt_out").find("*").attr("disabled", result); $("#div_opt_out").find('*').attr('disabled',result);
$("#button_add_blacklist").attr("disabled", false); $("#button_add_blacklist").attr('disabled', false);
$("#button_remove_blacklist").attr("disabled", false); $("#button_remove_blacklist").attr('disabled', false);
$("#custom_div_feedback").find("*").attr("disabled", false); if (value) { $('[name="button_subscription"]').addClass('clickable'); }
if (value) { else { $('[name="button_subscription"]').removeClass('clickable'); }
$('[name="button_subscription"]').addClass("clickable");
} else {
$('[name="button_subscription"]').removeClass("clickable");
}
} }

View File

@ -11,14 +11,14 @@ class UICase(HttpCase):
_tour_ready = "odoo.__DEBUG__.services['web_tour.tour'].tours.%s.ready" _tour_ready = "odoo.__DEBUG__.services['web_tour.tour'].tours.%s.ready"
def extract_url(self, mail, *args, **kwargs): def extract_url(self, mail, *args, **kwargs):
url = mail._get_unsubscribe_url(self.email) url = mail.mailing_id._get_unsubscribe_url(self.email, mail.res_id)
self.assertTrue(urls.url_parse(url).decode_query().get("token")) self.assertTrue(urls.url_parse(url).decode_query().get("token"))
self.assertTrue(url.startswith(self.domain)) self.assertTrue(url.startswith(self.domain))
self.url = url.replace(self.domain, "", 1) self.url = url.replace(self.domain, "", 1)
return True return True
def setUp(self): def setUp(self):
super(UICase, self).setUp() super().setUp()
self.email = "test.contact@example.com" self.email = "test.contact@example.com"
self.mail_postprocess_patch = mock.patch( self.mail_postprocess_patch = mock.patch(
"odoo.addons.mass_mailing.models.mail_mail.MailMail." "odoo.addons.mass_mailing.models.mail_mail.MailMail."
@ -47,7 +47,6 @@ class UICase(HttpCase):
"subject": "Test", "subject": "Test",
} }
) )
self.mailing._onchange_model_and_list()
# HACK https://github.com/odoo/odoo/pull/14429 # HACK https://github.com/odoo/odoo/pull/14429
self.mailing.body_html = """ self.mailing.body_html = """
<div> <div>
@ -59,7 +58,7 @@ class UICase(HttpCase):
def tearDown(self): def tearDown(self):
del self.email, self.lists, self.contact, self.mailing, self.url del self.email, self.lists, self.contact, self.mailing, self.url
super(UICase, self).tearDown() super().tearDown()
def test_contact_unsubscription(self): def test_contact_unsubscription(self):
"""Test a mass mailing contact that wants to unsubscribe.""" """Test a mass mailing contact that wants to unsubscribe."""

View File

@ -43,11 +43,11 @@
</field> </field>
</record> </record>
<act_window <record id="mail_unsubscription_reason_action" model="ir.actions.act_window">
id="mail_unsubscription_reason_action" <field name="name">Unsubscription Reasons</field>
name="Unsubscription Reasons" <field name="res_model">mail.unsubscription.reason</field>
res_model="mail.unsubscription.reason" <field name="view_mode">tree,form</field>
/> </record>
<menuitem <menuitem
id="mail_unsubscription_reason_menu" id="mail_unsubscription_reason_menu"

View File

@ -128,12 +128,11 @@
</field> </field>
</record> </record>
<act_window <record id="mail_unsubscription_action" model="ir.actions.act_window">
id="mail_unsubscription_action" <field name="name">(Un)subscriptions</field>
name="(Un)subscriptions" <field name="res_model">mail.unsubscription</field>
view_mode="tree,form,pivot,graph" <field name="view_mode">tree,form,pivot,graph</field>
res_model="mail.unsubscription" </record>
/>
<menuitem <menuitem
id="mail_unsubscription_menu" id="mail_unsubscription_menu"