From 345fdee4fb08fa54516fde26236661bbbdd59721 Mon Sep 17 00:00:00 2001 From: "Maruan Aguerdouh (magm)" Date: Fri, 27 Jan 2023 12:18:56 +0000 Subject: [PATCH] [FIX] mass_mailing: fix traceback when creating a mailing campaing with filters Steps to reproduce: - Get Marketing Automation module and mass_mailing module - Go to Marketing Automation > Configuration > Favorite filters - Create a new filter with for example, Recipient Model as Contact and the domain to be 'Name contains test' - Now we go back to Campaigns (Inside Marketing Automation) and create a new campaign with the filter that we have just created. - Create a new activity for this campaign with any mail template and save it. - Now just pres "start" to start the campaign. - After that you can also use "Launch a test" to see the trace-back. Issue: We receive a trace-back when we try to access to a value of a undefined object. That it is launch whenever we have a campaign with filters. Solution: Added the handling of the case when the inputElement is undefined. opw-3146908 closes odoo/odoo#117185 X-original-commit: b5b0d665ef2ea492bf7f9823da7f7982b0ddefa6 Signed-off-by: Thiry Renaud (reth) --- .../static/src/js/mailing_m2o_filter.js | 18 ++++- .../mass_mailing_favourite_filter_tests.js | 72 +++++++++++++++++++ 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/addons/mass_mailing/static/src/js/mailing_m2o_filter.js b/addons/mass_mailing/static/src/js/mailing_m2o_filter.js index 42d5c63ddfb..5efb631e7a2 100644 --- a/addons/mass_mailing/static/src/js/mailing_m2o_filter.js +++ b/addons/mass_mailing/static/src/js/mailing_m2o_filter.js @@ -57,14 +57,28 @@ export class FieldMany2OneMailingFilter extends Many2OneField { return; } const filterCount = this.props.record.data.mailing_filter_count; - document.querySelectorAll('.o_field_many2one_selection > .o_input_dropdown')[1].classList.toggle('d-none', !filterCount); + const dropdown = document.querySelectorAll('.o_field_many2one_selection > .o_input_dropdown')[1] + if (dropdown) { + 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.props.record.data[this.props.domain_field] || []).toString(); const filterDomain = new Domain(this.props.record.data.mailing_filter_domain || []).toString(); + + const modelFieldElement = this.props.model_field && document.querySelector( + `input#${this.props.model_field},div [name="${this.props.model_field}"]`); + + let value = ""; + if (modelFieldElement && modelFieldElement.tagName === "span") { + value = modelFieldElement.textContent; + } else if (modelFieldElement && modelFieldElement.tagName === "input") { + value = modelFieldElement.value; + } + el.classList.toggle('d-none', recordDomain === '[]'); this.filter.canSaveFilter = !this.props.record.data.mailing_filter_id - || !document.querySelector(`input#${this.props.model_field}`).value.length + || value.length || this.state.isFloating || filterDomain !== recordDomain; } diff --git a/addons/mass_mailing/static/tests/mass_mailing_favourite_filter_tests.js b/addons/mass_mailing/static/tests/mass_mailing_favourite_filter_tests.js index b2ffa268db4..18750d5c68c 100644 --- a/addons/mass_mailing/static/tests/mass_mailing_favourite_filter_tests.js +++ b/addons/mass_mailing/static/tests/mass_mailing_favourite_filter_tests.js @@ -407,5 +407,77 @@ QUnit.module('favorite filter widget', (hooks) => { assert.isNotVisible(fixture.querySelector('.o_mass_mailing_remove_filter'), "should not have option to remove filter because mailing domain is changed"); }); + + QUnit.test('filter widget works in edit and readonly', async (assert) => { + assert.expect(4); + + serverData.models.partner = { + fields: { + name: { string: 'Name', type: 'char', searchable: true }, + }, + }; + + serverData.models['mailing.filter'].records = [{ + id: 1, + name: 'Azure Partner Only', + mailing_domain: "[['name','=', 'Azure Interior']]", + mailing_model_id: 2, + }]; + + serverData.models['mailing.mailing'].records.push({ + id: 3, + display_name: 'Partner Event promotion', + subject: 'Early bird discount for Partners!', + mailing_model_id: 2, + mailing_model_name: 'partner', + mailing_filter_count: 1, + mailing_filter_domain: "[['name','=', 'Azure Interior']]", + mailing_filter_id: 1, + mailing_domain: "[['name','=', 'Azure Interior']]", + state: 'draft', + }); + + serverData.models['mailing.mailing'].fields.state = { + string: 'Stage', + type: 'selection', + selection: [['draft', 'Draft'], ['running', 'Running']] + }; + + serverData.models['mailing.mailing'].onchanges = { + mailing_filter_id: obj => { + obj.mailing_domain = serverData.models['mailing.filter'].records.filter(r => r.id === obj.mailing_filter_id)[0].mailing_domain; + }, + }; + + await makeView({ + type: "form", + resModel: "mailing.mailing", + resId: 3, + serverData, + arch: `
+ + + + + + + + + + + `, + }); + + await testUtils.nextTick(); + const selectField = fixture.querySelector("button[data-value='running']"); + assert.containsOnce(fixture, "div[name='mailing_model_id']:not(.o_readonly_modifier)"); + assert.ok(fixture.querySelector(".o_mass_mailing_save_filter_container:not(.d-none)")); + // set to 'running' + selectField.dispatchEvent(new Event('click')); + selectField.dispatchEvent(new Event('change')); + await testUtils.nextTick(); + assert.containsOnce(fixture, "div[name='mailing_model_id'].o_readonly_modifier"); + assert.ok(fixture.querySelector(".o_mass_mailing_save_filter_container:not(.d-none)")); + }); }); });