[FIX] web_editor: onAttachmentChange only composer

Due to a previous fix, attachments uploaded through media dialog would appear in the attachments of mail marketting.
That fix prevents attachments from 'dangling' and being garbage collected later.

That fix is now limited to the mail composer in this commit as attachments are only garbage collected for that model, for now.

related commit: c112361bf9e2f5e7b087c5e5b9a31879856b1da4

task 3003939

closes odoo/odoo#103038

X-original-commit: 69fdca133b06eb66443635bc52d380233580ef51
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Renaud Thiry
2022-10-11 14:10:25 +02:00
parent 52d46e1e76
commit 96c8dd3ca8
9 changed files with 30 additions and 28 deletions
@@ -16,37 +16,38 @@ const { useEffect } = owl;
QUnit.module('field html file upload', {
beforeEach: function () {
this.data = weTestUtils.wysiwygData({
'note.note': {
'mail.compose.message': {
fields: {
display_name: {
string: "Displayed name",
type: "char"
},
header: {
string: "Header",
type: "html",
required: true,
},
body: {
string: "Message",
string: "Message Body inline (to send)",
type: "html"
},
attachment_ids: {
string: "Attachments",
type: "many2many",
relation: "ir.attachment",
}
},
records: [{
id: 1,
display_name: "first record",
header: "<p> &nbsp;&nbsp; <br> </p>",
body: "<p>toto toto toto</p><p>tata</p>",
display_name: "Some Composer",
body: "Hello",
attachment_ids: [],
}],
},
});
},
}, function () {
QUnit.test('media dialog: upload', async function (assert) {
assert.expect(3);
assert.expect(4);
const onAttachmentChangeTriggered = testUtils.makeTestPromise();
patchWithCleanup(HtmlField.prototype, {
'_onAttachmentChange': function (event) {
this._super(event);
onAttachmentChangeTriggered.resolve(true);
}
});
@@ -75,16 +76,17 @@ QUnit.module('field html file upload', {
1: {
id: 1,
name: "test",
res_model: "note.note",
res_model: "mail.compose.message",
type: "ir.actions.act_window",
views: [[false, "form"]],
},
};
serverData.views = {
"note.note,false,search": "<search></search>",
"note.note,false,form": `
"mail.compose.message,false,search": "<search></search>",
"mail.compose.message,false,form": `
<form>
<field name="body" type="html"/>
<field name="attachment_ids" widget="many2many_binary"/>
</form>`,
};
const mockRPC = (route, args) => {
@@ -122,9 +124,14 @@ QUnit.module('field html file upload', {
fileInputs.forEach(input => {
input.dispatchEvent(new Event('change', {}));
});
assert.ok(await Promise.race([onChangeTriggered, new Promise((res, _) => setTimeout(() => res(false), 400))]),
"File change event was not triggered");
assert.ok(await Promise.race([onAttachmentChangeTriggered, new Promise((res, _) => setTimeout(() => res(false), 400))]),
"_onAttachmentChange was not called with the new attachment, necessary for unsused upload cleanup on backend");
// wait to check that dom is properly updated
await new Promise((res, _) => setTimeout(() => res(false), 400));
assert.ok(fixture.querySelector('.o_attachment[title="test.jpg"]'));
});
});
@@ -2370,8 +2370,6 @@ var FieldMany2ManyBinaryMultiFiles = AbstractField.extend({
fieldsToFetch: {
name: {type: 'char'},
mimetype: {type: 'char'},
res_id: {type: 'number'},
access_token: {type: 'char'},
},
events: {
'click .o_attach': '_onAttach',
+1 -1
View File
@@ -1338,7 +1338,7 @@
<t t-name="FieldBinaryFileUploader.attachment_preview">
<t t-set="url" t-value="widget.metadata[file.id] ? widget.metadata[file.id].url : false"/>
<t t-if="file.data" t-set="file" t-value="file.data"/>
<t t-set="editable" t-value="widget.mode === 'edit' and !(file.res_id === 0 and file.access_token)"/>
<t t-set="editable" t-value="widget.mode === 'edit'"/>
<t t-if="file.mimetype" t-set="mimetype" t-value="file.mimetype"/>
<div t-attf-class="o_attachment o_attachment_many2many #{ editable ? 'o_attachment_editable' : '' } #{upload ? 'o_attachment_uploading' : ''}" t-att-title="file.name">
<div class="o_attachment_wrap">
@@ -59,8 +59,6 @@ Many2ManyBinaryField.supportedTypes = ["many2many"];
Many2ManyBinaryField.fieldsToFetch = {
name: { type: "char" },
mimetype: { type: "char" },
res_id: { type: "number" },
access_token: { type: "char" },
};
Many2ManyBinaryField.isEmpty = () => false;
@@ -25,7 +25,7 @@
</t>
<t t-name="Many2ManyBinaryField.attachment_preview" owl="1">
<t t-set="editable" t-value="!props.readonly and !(file.res_id === 0 and file.access_token)"/>
<t t-set="editable" t-value="!props.readonly"/>
<div t-attf-class="o_attachment o_attachment_many2many #{ editable ? 'o_attachment_editable' : '' } #{upload ? 'o_attachment_uploading' : ''}" t-att-title="file.name">
<div class="o_attachment_wrap">
<t t-set="ext" t-value="getExtension(file)"/>
@@ -2977,14 +2977,11 @@ QUnit.module('Legacy relational_fields', {
fields: {
name: {string:"Name", type: "char"},
mimetype: {string: "Mimetype", type: "char"},
res_id: {type: "number"},
access_token: {type: "char"}
},
records: [{
id: 17,
name: 'Marley&Me.jpg',
mimetype: 'jpg',
res_id: 1, //non-zero to avoid transiant model editor attachment protection
}],
};
this.data.turtle.fields.picture_ids = {
@@ -3008,7 +3005,7 @@ QUnit.module('Legacy relational_fields', {
mockRPC: function (route, args) {
assert.step(route);
if (route === '/web/dataset/call_kw/ir.attachment/read') {
assert.deepEqual(args.args[1], ['name', 'mimetype', 'res_id', 'access_token']);
assert.deepEqual(args.args[1], ['name', 'mimetype']);
}
return this._super.apply(this, arguments);
},
@@ -96,7 +96,7 @@ QUnit.module("Fields", (hooks) => {
assert.step(route);
}
if (route === "/web/dataset/call_kw/ir.attachment/read") {
assert.deepEqual(args.args[1], ["name", "mimetype", "res_id", "access_token"]);
assert.deepEqual(args.args[1], ["name", "mimetype"]);
}
},
});
@@ -334,10 +334,11 @@ var FieldHtml = basic_fields.DebouncedField.extend(DynamicPlaceholderFieldMixin)
* @param {Object} event the event containing attachment data
*/
_onAttachmentChange: function (event) {
const attachments = event.data;
if (!this.fieldNameAttachment) {
// This only needs to happen for the composer for now
if (!this.fieldNameAttachment || this.model !== 'mail.compose.message') {
return;
}
const attachments = event.data;
this.trigger_up('field_changed', {
dataPointID: this.dataPointID,
changes: _.object([this.fieldNameAttachment], [{
@@ -497,7 +497,8 @@ export class HtmlField extends Component {
return getWysiwygClass();
}
_onAttachmentChange(attachment) {
if (!this.props.record.fieldNames.includes('attachment_ids')) {
// This only needs to happen for the composer for now
if (!(this.props.record.fieldNames.includes('attachment_ids') && this.props.record.resModel === 'mail.compose.message')) {
return;
}
this.props.record.update(_.object(['attachment_ids'], [{