From 222ae02ceae1eab69f22dc90326e48d56bdc2abc Mon Sep 17 00:00:00 2001 From: Rahul Prajapati Date: Fri, 20 May 2022 10:15:37 +0000 Subject: [PATCH] [IMP] mail: add hover download button on image attachments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PURPOSE Improve how image attachments are downloaded from the chatter by adding the `download` button when hovering image files SPECIFICATIONS add a `Download` button (icon) on the bottom right corner of image attachments on hover Task-2802810 closes odoo/odoo#92013 Signed-off-by: Alexandre Kühn (aku) --- .../attachment_image/attachment_image.xml | 15 +++--- .../static/src/models/attachment_image.js | 46 +++++++++++++++++-- .../components/message_tests.js | 30 ++++++++++++ 3 files changed, 79 insertions(+), 12 deletions(-) diff --git a/addons/mail/static/src/components/attachment_image/attachment_image.xml b/addons/mail/static/src/components/attachment_image/attachment_image.xml index 65643900d17..0b0b76d3fa5 100644 --- a/addons/mail/static/src/components/attachment_image/attachment_image.xml +++ b/addons/mail/static/src/components/attachment_image/attachment_image.xml @@ -20,15 +20,14 @@ - -
- +
+ - +
+ +
+
diff --git a/addons/mail/static/src/models/attachment_image.js b/addons/mail/static/src/models/attachment_image.js index eb345d7905e..fd61611f49a 100644 --- a/addons/mail/static/src/models/attachment_image.js +++ b/addons/mail/static/src/models/attachment_image.js @@ -3,15 +3,36 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; import { clear, insertAndReplace, replace } from '@mail/model/model_field_command'; +import { isEventHandled, markEventHandled } from '@mail/utils/utils'; registerModel({ name: 'AttachmentImage', identifyingFields: ['attachmentList', 'attachment'], recordMethods: { /** - * Opens the attachment viewer when clicking on viewable attachment. + * Called when clicking on download icon. + * + * @param {MouseEvent} ev */ - onClickImage() { + onClickDownload(ev) { + markEventHandled(ev, 'AttachmentImage.onClickDownload'); + if (!this.exists()) { + return; + } + this.attachment.download(); + }, + /** + * Opens the attachment viewer when clicking on viewable attachment. + * + * @param {MouseEvent} ev + */ + onClickImage(ev) { + if (isEventHandled(ev, 'AttachmentImage.onClickDownload')) { + return; + } + if (isEventHandled(ev, 'AttachmentImage.onClickUnlink')) { + return; + } if (!this.attachment || !this.attachment.isViewable) { return; } @@ -26,8 +47,8 @@ registerModel({ * @param {MouseEvent} ev */ onClickUnlink(ev) { - ev.stopPropagation(); // prevents from opening viewer - if (!this.attachment) { + markEventHandled(ev, 'AttachmentImage.onClickUnlink'); + if (!this.exists()) { return; } if (this.attachmentList.composerViewOwner) { @@ -36,6 +57,16 @@ registerModel({ this.update({ attachmentDeleteConfirmDialog: insertAndReplace() }); } }, + /** + * @private + * @returns {boolean} + */ + _computeHasDownloadButton() { + if (!this.attachment || !this.attachmentList) { + return clear(); + } + return !this.attachmentList.composerViewOwner && !this.attachment.isUploading; + }, /** * @private * @returns {number} @@ -99,6 +130,13 @@ registerModel({ readonly: true, required: true, }), + /** + * Determines whether `this` should display a download button. + */ + hasDownloadButton: attr({ + compute: '_computeHasDownloadButton', + default: false, + }), /** * Determines the max height of this attachment image in px. */ diff --git a/addons/mail/static/tests/qunit_suite_tests/components/message_tests.js b/addons/mail/static/tests/qunit_suite_tests/components/message_tests.js index 86439f030ff..45a4d875ad8 100644 --- a/addons/mail/static/tests/qunit_suite_tests/components/message_tests.js +++ b/addons/mail/static/tests/qunit_suite_tests/components/message_tests.js @@ -698,6 +698,36 @@ QUnit.test('prevent attachment delete on non-authored message in channels', asyn ); }); +QUnit.test('allow attachment image download on message', async function (assert) { + assert.expect(1); + + const pyEnv = await startServer(); + const mailChannelId1 = pyEnv['mail.channel'].create({}); + const irAttachmentId1 = pyEnv['ir.attachment'].create({ + name: "Blah.jpg", + mimetype: 'image/jpeg', + }); + pyEnv['mail.message'].create({ + attachment_ids: [irAttachmentId1], + body: '

Test

', + model: 'mail.channel', + res_id: mailChannelId1, + }); + const { openDiscuss } = await start({ + discuss: { + context: { + active_id: mailChannelId1, + }, + }, + }); + await openDiscuss(); + assert.containsOnce( + document.body, + '.o_AttachmentImage_actionDownload', + "should have download attachment button" + ); +}); + QUnit.test('subtype description should be displayed if it is different than body', async function (assert) { assert.expect(2);