From c297dc8604faa3855431a938136e9c26c4ff812a Mon Sep 17 00:00:00 2001 From: MAHAMADASIF ANSARI Date: Thu, 31 Mar 2022 12:18:30 +0000 Subject: [PATCH] [IMP] mass_mailing: improve UX of favorite filter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If you do not have favorite filters available in the mass mailing for selected model, we display empty drop down, which is not ideal. This commit improves the behavior with following changes: - If there is no filter available (for this target) and no condition set in the mailing domain, do not display anything - If mailing domain is set but there is not filter available, show a custom label "Save Filter as Favorite" save icon next to it Ent PR: https://github.com/odoo/enterprise/pull/26308 task-2711258 closes odoo/odoo#87673 Related: odoo/enterprise#26308 Signed-off-by: Warnon Aurélien (awa) --- addons/mass_mailing/models/mailing.py | 21 ++- .../static/src/js/mailing_filter_widget.js | 20 ++- .../static/src/xml/mailing_filter_widget.xml | 5 +- .../mass_mailing_favourite_filter_tests.js | 126 ++++++++++++++++++ .../views/mailing_mailing_views.xml | 1 + 5 files changed, 161 insertions(+), 12 deletions(-) diff --git a/addons/mass_mailing/models/mailing.py b/addons/mass_mailing/models/mailing.py index 4f203d3578c..8bd8b75c6ed 100644 --- a/addons/mass_mailing/models/mailing.py +++ b/addons/mass_mailing/models/mailing.py @@ -126,11 +126,6 @@ class MassMailing(models.Model): mailing_domain = fields.Char( string='Domain', compute='_compute_mailing_domain', readonly=False, store=True) - mailing_filter_id = fields.Many2one( - 'mailing.filter', string='Favorite Filter', - domain="[('mailing_model_name', '=', mailing_model_name)]", - compute='_compute_mailing_filter_id', readonly=False, store=True) - mailing_filter_domain = fields.Char('Favorite filter domain', related='mailing_filter_id.mailing_domain') mail_server_available = fields.Boolean( compute='_compute_mail_server_available', help="Technical field used to know if the user has activated the outgoing mail server option in the settings") @@ -138,6 +133,13 @@ class MassMailing(models.Model): default=_get_default_mail_server_id, help="Use a specific mail server in priority. Otherwise Odoo relies on the first outgoing mail server available (based on their sequencing) as it does for normal mails.") contact_list_ids = fields.Many2many('mailing.list', 'mail_mass_mailing_list_rel', string='Mailing Lists') + # Mailing Filter + mailing_filter_id = fields.Many2one( + 'mailing.filter', string='Favorite Filter', + domain="[('mailing_model_name', '=', mailing_model_name)]", + compute='_compute_mailing_filter_id', readonly=False, store=True) + mailing_filter_domain = fields.Char('Favorite filter domain', related='mailing_filter_id.mailing_domain') + mailing_filter_count = fields.Integer('# Favorite Filters', compute='_compute_mailing_filter_count') # A/B Testing ab_testing_completed = fields.Boolean(related='campaign_id.ab_testing_completed', store=True) ab_testing_description = fields.Html('A/B Testing Description', compute="_compute_ab_testing_description") @@ -331,6 +333,15 @@ class MassMailing(models.Model): elif mailing.reply_to_mode == 'update': mailing.reply_to = False + @api.depends('mailing_model_id', 'mailing_domain') + def _compute_mailing_filter_count(self): + filter_data = self.env['mailing.filter']._read_group([ + ('mailing_model_id', 'in', self.mailing_model_id.ids) + ], ['mailing_model_id'], ['mailing_model_id']) + mapped_data = {data['mailing_model_id'][0]: data['mailing_model_id_count'] for data in filter_data} + for mailing in self: + mailing.mailing_filter_count = mapped_data.get(mailing.mailing_model_id.id, 0) + @api.depends('mailing_model_id') def _compute_mailing_model_real(self): for mailing in self: diff --git a/addons/mass_mailing/static/src/js/mailing_filter_widget.js b/addons/mass_mailing/static/src/js/mailing_filter_widget.js index d7f0ebd37dc..d0ff0f081a9 100644 --- a/addons/mass_mailing/static/src/js/mailing_filter_widget.js +++ b/addons/mass_mailing/static/src/js/mailing_filter_widget.js @@ -2,6 +2,7 @@ import { FieldMany2One } from 'web.relational_fields'; import core from 'web.core'; +import Domain from 'web.Domain'; import fieldRegistry from 'web.field_registry'; const _t = core._t; @@ -67,8 +68,9 @@ const FieldMailingFilter = FieldMany2One.extend({ }, /** - * Updates the 'Add to favorite' / 'Remove' star icons' visibility based on - * the current state. + * Updates the 'Add to favorite' / 'Remove' icons' visibility based on the + * current state, and shows the custom message when no filter is available + * for the selected model. * * The filter can be saved if one of those conditions is matched: * - No favorite filter is currently set @@ -80,12 +82,18 @@ const FieldMailingFilter = FieldMany2One.extend({ * @private */ _updateFilterIcons: function () { - const hasDomain = this.recordData[this.domainFieldName] && this.recordData[this.domainFieldName] !== '[]'; - this.el.querySelector('.o_mass_mailing_filter_container').classList.toggle('invisible', !hasDomain); + const filterCount = this.recordData.mailing_filter_count; + this.el.querySelector('.o_mass_mailing_no_filter').classList.toggle('d-none', filterCount); + this.el.querySelector('.o_field_many2one_selection > .o_input_dropdown').classList.toggle('d-none', !filterCount); + // By default, domains in recordData are in string format, but adding / removing a leaf from domain widget converts + // value into object, so we use 'Domain' class to convert them in same (string) format, allowing proper comparison. + const recordDomain = new Domain(this.recordData[this.domainFieldName] || []).toString(); + const filterDomain = new Domain(this.recordData.mailing_filter_domain || []).toString(); + this.el.querySelector('.o_mass_mailing_filter_container').classList.toggle('d-none', recordDomain === '[]'); const canSaveFilter = !this.recordData.mailing_filter_id || !this.$input.val().length || this.floating - || this.recordData.mailing_filter_domain !== this.recordData[this.domainFieldName]; + || filterDomain !== recordDomain; this.el.querySelector('.o_mass_mailing_save_filter_container').classList.toggle('d-none', !canSaveFilter); this.el.querySelector('.o_mass_mailing_remove_filter').classList.toggle('d-none', canSaveFilter); }, @@ -158,7 +166,7 @@ const FieldMailingFilter = FieldMany2One.extend({ // Prevent multiple clicks to avoid trying to deleting same record multiple times. ev.target.disabled = true; // Avoid calling any 'onchange' (that depends on filter and might reset the domain) immediately - // after filter is removed. It should have any side effects because we don't want to change + // after filter is removed. It shouldn't have any side effects because we don't want to change // anything in any case when filter is unliked with with this widget. this._setValue(false, {notifyChange: false}); await this._rpc({ diff --git a/addons/mass_mailing/static/src/xml/mailing_filter_widget.xml b/addons/mass_mailing/static/src/xml/mailing_filter_widget.xml index 7b343dda1f8..916843a8920 100644 --- a/addons/mass_mailing/static/src/xml/mailing_filter_widget.xml +++ b/addons/mass_mailing/static/src/xml/mailing_filter_widget.xml @@ -5,7 +5,10 @@
- + + Save as Favorite Filter + +