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 + +