[FIX] mail: handles unlink button spam on attachments
Before this commit, attempting to delete attachments multiple times could result in errors, especially on slow networks. This commit fixes this issue. task-2363522 closes odoo/odoo#63189 X-original-commit: 528adfb313ab3c8d4aeb3309aa7371301ab8085e Signed-off-by: Sébastien Theys (seb) <seb@odoo.com> Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
@@ -595,6 +595,41 @@ QUnit.test('close attachment viewer', async function (assert) {
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test('clicking on the delete attachment button multiple times should do the rpc only once', async function (assert) {
|
||||
assert.expect(2);
|
||||
await this.start({
|
||||
async mockRPC(route, args) {
|
||||
if (args.method === "unlink" && args.model === "ir.attachment") {
|
||||
assert.step('attachment_unlink');
|
||||
return;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
});
|
||||
const attachment = this.env.models['mail.attachment'].create({
|
||||
filename: "test.txt",
|
||||
id: 750,
|
||||
mimetype: 'text/plain',
|
||||
name: "test.txt",
|
||||
});
|
||||
await this.createAttachmentComponent(attachment, {
|
||||
detailsMode: 'hover',
|
||||
});
|
||||
await afterNextRender(() => {
|
||||
document.querySelector('.o_Attachment_actionUnlink').click();
|
||||
});
|
||||
|
||||
await afterNextRender(() => {
|
||||
document.querySelector('.o_AttachmentDeleteConfirmDialog_confirmButton').click();
|
||||
document.querySelector('.o_AttachmentDeleteConfirmDialog_confirmButton').click();
|
||||
document.querySelector('.o_AttachmentDeleteConfirmDialog_confirmButton').click();
|
||||
});
|
||||
assert.verifySteps(
|
||||
['attachment_unlink'],
|
||||
"The unlink method must be called once"
|
||||
);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -97,12 +97,20 @@ function factory(dependencies) {
|
||||
* Remove this attachment globally.
|
||||
*/
|
||||
async remove() {
|
||||
if (this.isUnlinkPending) {
|
||||
return;
|
||||
}
|
||||
if (!this.isTemporary) {
|
||||
await this.async(() => this.env.services.rpc({
|
||||
model: 'ir.attachment',
|
||||
method: 'unlink',
|
||||
args: [this.id],
|
||||
}, { shadow: true }));
|
||||
this.update({ isUnlinkPending: true });
|
||||
try {
|
||||
await this.async(() => this.env.services.rpc({
|
||||
model: 'ir.attachment',
|
||||
method: 'unlink',
|
||||
args: [this.id],
|
||||
}, { shadow: true }));
|
||||
} finally {
|
||||
this.update({ isUnlinkPending: false });
|
||||
}
|
||||
} else if (this.uploadingAbortController) {
|
||||
this.uploadingAbortController.abort();
|
||||
}
|
||||
@@ -335,6 +343,12 @@ function factory(dependencies) {
|
||||
compute: '_computeIsTextFile',
|
||||
dependencies: ['fileType'],
|
||||
}),
|
||||
/**
|
||||
* True if an unlink RPC is pending, used to prevent multiple unlink attempts.
|
||||
*/
|
||||
isUnlinkPending: attr({
|
||||
default: false,
|
||||
}),
|
||||
isViewable: attr({
|
||||
compute: '_computeIsViewable',
|
||||
dependencies: [
|
||||
|
||||
Reference in New Issue
Block a user