From 0df4b0029b9af321d36e830e68f3a2c70e1512b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20K=C3=BChn?= Date: Wed, 2 Feb 2022 17:47:20 +0000 Subject: [PATCH] [IMP] mail, snailmail: convert legacy dialog with t-ref to model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation to using Owl 2 in discuss code. task-2738648 closes odoo/odoo#83598 Signed-off-by: Sébastien Theys (seb) --- .../attachment_box/attachment_box.xml | 1 - .../tests/attachment_box_tests.js | 2 +- .../attachment_card/attachment_card.js | 8 +- .../attachment_card/attachment_card.xml | 7 -- .../attachment_delete_confirm.js | 69 ++---------- .../attachment_delete_confirm.xml | 17 +-- .../attachment_image/attachment_image.js | 8 +- .../attachment_image/attachment_image.xml | 7 -- .../attachment_list/attachment_list.js | 8 +- .../attachment_list/attachment_list.xml | 4 +- .../tests/attachment_list_tests.js | 1 + .../delete_message_confirm.js | 19 ++-- .../delete_message_confirm.xml | 25 +++-- .../static/src/components/dialog/dialog.scss | 14 +-- .../static/src/components/dialog/dialog.xml | 8 +- .../static/src/components/message/message.js | 11 +- .../static/src/components/message/message.xml | 2 +- .../components/message/tests/message_tests.js | 2 +- .../message_action_list.xml | 1 - .../thread_view/tests/thread_view_tests.js | 6 +- .../attachment_box_view.js | 7 -- .../models/attachment_card/attachment_card.js | 21 +--- .../attachment_delete_confirm_view.js | 90 ++++++++++++++++ .../attachment_image/attachment_image.js | 21 +--- .../src/models/composer_view/composer_view.js | 2 +- .../delete_message_confirm_view.js | 68 ++++++++++++ .../mail/static/src/models/dialog/dialog.js | 101 +++++++++++++++++- .../message_action_list.js | 47 +------- .../src/models/message_view/message_view.js | 31 +++--- .../static/src/components/message/message.js | 76 ------------- .../static/src/components/message/message.xml | 6 -- .../components/message/tests/message_tests.js | 3 + .../snailmail_error/snailmail_error.js | 78 ++------------ .../snailmail_error/snailmail_error.xml | 48 +++++---- .../static/src/models/dialog/dialog.js | 67 ++++++++++++ .../src/models/message_view/message_view.js | 56 ++++++++++ .../snailmail_error_view.js | 81 ++++++++++++++ 37 files changed, 599 insertions(+), 424 deletions(-) create mode 100644 addons/mail/static/src/models/attachment_delete_confirm_view/attachment_delete_confirm_view.js create mode 100644 addons/mail/static/src/models/delete_message_confirm_view/delete_message_confirm_view.js delete mode 100644 addons/snailmail/static/src/components/message/message.js create mode 100644 addons/snailmail/static/src/models/dialog/dialog.js create mode 100644 addons/snailmail/static/src/models/message_view/message_view.js create mode 100644 addons/snailmail/static/src/models/snailmail_error_view/snailmail_error_view.js diff --git a/addons/mail/static/src/components/attachment_box/attachment_box.xml b/addons/mail/static/src/components/attachment_box/attachment_box.xml index 1cc9667d754..7b5670cf7a7 100644 --- a/addons/mail/static/src/components/attachment_box/attachment_box.xml +++ b/addons/mail/static/src/components/attachment_box/attachment_box.xml @@ -22,7 +22,6 @@ - +
+ +

Confirmation

+
+

+


+
+ + +
- +
diff --git a/addons/mail/static/src/components/attachment_image/attachment_image.js b/addons/mail/static/src/components/attachment_image/attachment_image.js index 8f5cc0f3ad6..de60930afbf 100644 --- a/addons/mail/static/src/components/attachment_image/attachment_image.js +++ b/addons/mail/static/src/components/attachment_image/attachment_image.js @@ -25,13 +25,7 @@ export class AttachmentImage extends Component { } Object.assign(AttachmentImage, { - props: { - localId: String, - onAttachmentRemoved: { - type: Function, - optional: true, - }, - }, + props: { localId: String }, template: 'mail.AttachmentImage', }); 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 367b0619ad6..4c2e776ba0a 100644 --- a/addons/mail/static/src/components/attachment_image/attachment_image.xml +++ b/addons/mail/static/src/components/attachment_image/attachment_image.xml @@ -29,13 +29,6 @@ - - - diff --git a/addons/mail/static/src/components/attachment_list/attachment_list.js b/addons/mail/static/src/components/attachment_list/attachment_list.js index 352cd279609..95c5a2e0632 100644 --- a/addons/mail/static/src/components/attachment_list/attachment_list.js +++ b/addons/mail/static/src/components/attachment_list/attachment_list.js @@ -16,13 +16,7 @@ export class AttachmentList extends Component { } Object.assign(AttachmentList, { - props: { - localId: String, - onAttachmentRemoved: { - type: Function, - optional: true, - }, - }, + props: { localId: String }, template: 'mail.AttachmentList', }); diff --git a/addons/mail/static/src/components/attachment_list/attachment_list.xml b/addons/mail/static/src/components/attachment_list/attachment_list.xml index 99683ba7269..b3174ffcf03 100644 --- a/addons/mail/static/src/components/attachment_list/attachment_list.xml +++ b/addons/mail/static/src/components/attachment_list/attachment_list.xml @@ -6,12 +6,12 @@
- +
- +
diff --git a/addons/mail/static/src/components/attachment_list/tests/attachment_list_tests.js b/addons/mail/static/src/components/attachment_list/tests/attachment_list_tests.js index 50787205ccc..20dcebf0ffb 100644 --- a/addons/mail/static/src/components/attachment_list/tests/attachment_list_tests.js +++ b/addons/mail/static/src/components/attachment_list/tests/attachment_list_tests.js @@ -272,6 +272,7 @@ QUnit.test('clicking on the delete attachment button multiple times should do th assert.expect(2); const { createMessageComponent } = await this.start({ + hasDialog: true, async mockRPC(route, args) { if (route === '/mail/attachment/delete') { assert.step('attachment_unlink'); diff --git a/addons/mail/static/src/components/delete_message_confirm/delete_message_confirm.js b/addons/mail/static/src/components/delete_message_confirm/delete_message_confirm.js index ba4ee2d6f77..e08002137fa 100644 --- a/addons/mail/static/src/components/delete_message_confirm/delete_message_confirm.js +++ b/addons/mail/static/src/components/delete_message_confirm/delete_message_confirm.js @@ -1,9 +1,8 @@ /** @odoo-module **/ +import { useComponentToModel } from '@mail/component_hooks/use_component_to_model/use_component_to_model'; import { registerMessagingComponent } from '@mail/utils/messaging_component'; -import Dialog from 'web.OwlDialog'; - const { Component } = owl; export class DeleteMessageConfirm extends Component { @@ -13,24 +12,20 @@ export class DeleteMessageConfirm extends Component { */ setup() { super.setup(); - this.title = this.env._t("Confirmation"); + useComponentToModel({ fieldName: 'component', modelName: 'DeleteMessageConfirmView' }); } /** - * @returns {MessageActionList} + * @returns {DeleteMessageConfirmView} */ - get messageActionList() { - return this.messaging && this.messaging.models['MessageActionList'].get(this.props.localId); + get deleteMessageConfirmView() { + return this.messaging && this.messaging.models['DeleteMessageConfirmView'].get(this.props.localId); } + } Object.assign(DeleteMessageConfirm, { - components: { - Dialog, - }, - props: { - localId: String, - }, + props: { localId: String }, template: 'mail.DeleteMessageConfirm', }); diff --git a/addons/mail/static/src/components/delete_message_confirm/delete_message_confirm.xml b/addons/mail/static/src/components/delete_message_confirm/delete_message_confirm.xml index a3d51975978..693a8be649d 100644 --- a/addons/mail/static/src/components/delete_message_confirm/delete_message_confirm.xml +++ b/addons/mail/static/src/components/delete_message_confirm/delete_message_confirm.xml @@ -1,18 +1,21 @@ - - -

Are you sure you want to delete this message?

-
- +
+ +

Confirmation

+
+

Are you sure you want to delete this message?

+
+
- Pay attention: The followers of this document who were notified by email will still be able to read the content of this message and reply to it. - - - - + Pay attention: The followers of this document who were notified by email will still be able to read the content of this message and reply to it. +
+
+ + +
-
+
diff --git a/addons/mail/static/src/components/dialog/dialog.scss b/addons/mail/static/src/components/dialog/dialog.scss index 14c1cf31753..ac7b264d8e3 100644 --- a/addons/mail/static/src/components/dialog/dialog.scss +++ b/addons/mail/static/src/components/dialog/dialog.scss @@ -14,10 +14,12 @@ z-index: $zindex-modal; } -// ------------------------------------------------------------------ -// Style -// ------------------------------------------------------------------ - -.o_Dialog { - background-color: rgba($black, 0.7); +.o_Dialog_componentLargeSize { + min-width: Min(95vw, $o-modal-lg); + max-width: 95vw; +} + +.o_Dialog_componentMediumSize { + min-width: Min(95vw, $o-modal-md); + max-width: 95vw; } diff --git a/addons/mail/static/src/components/dialog/dialog.xml b/addons/mail/static/src/components/dialog/dialog.xml index d7cd8748c27..31ef1928b40 100644 --- a/addons/mail/static/src/components/dialog/dialog.xml +++ b/addons/mail/static/src/components/dialog/dialog.xml @@ -2,12 +2,14 @@ -
+
diff --git a/addons/mail/static/src/components/message/message.js b/addons/mail/static/src/components/message/message.js index 4c36264cb4e..917f0e212c9 100644 --- a/addons/mail/static/src/components/message/message.js +++ b/addons/mail/static/src/components/message/message.js @@ -153,7 +153,7 @@ export class Message extends Component { this.messageView.messageActionList && ( this.messageView.messageActionList.reactionPopoverView || - this.messageView.messageActionList.showDeleteConfirm + this.messageView.messageActionList.deleteConfirmDialog ) ) ); @@ -543,15 +543,6 @@ export class Message extends Component { this.messageView.message.author.openProfile(); } - /** - * @private - * @param {MouseEvent} ev - */ - _onClickFailure(ev) { - markEventHandled(ev, 'Message.ClickFailure'); - this.messageView.message.openResendAction(); - } - /** * @private * @param {MouseEvent} ev diff --git a/addons/mail/static/src/components/message/message.xml b/addons/mail/static/src/components/message/message.xml index 48253937e20..839af71082e 100644 --- a/addons/mail/static/src/components/message/message.xml +++ b/addons/mail/static/src/components/message/message.xml @@ -102,7 +102,7 @@ - + diff --git a/addons/mail/static/src/components/message/tests/message_tests.js b/addons/mail/static/src/components/message/tests/message_tests.js index 7a83b47c3ad..8ad2ff144a7 100644 --- a/addons/mail/static/src/components/message/tests/message_tests.js +++ b/addons/mail/static/src/components/message/tests/message_tests.js @@ -654,7 +654,7 @@ QUnit.test('only show messaging seen indicator if authored by me, after last see QUnit.test('allow attachment delete on authored message', async function (assert) { assert.expect(5); - const { createMessageComponent } = await this.start(); + const { createMessageComponent } = await this.start({ hasDialog: true }); const message = this.messaging.models['Message'].create({ attachments: insertAndReplace({ filename: "BLAH.jpg", diff --git a/addons/mail/static/src/components/message_action_list/message_action_list.xml b/addons/mail/static/src/components/message_action_list/message_action_list.xml index 919b642b14c..62c0f1118a7 100644 --- a/addons/mail/static/src/components/message_action_list/message_action_list.xml +++ b/addons/mail/static/src/components/message_action_list/message_action_list.xml @@ -14,7 +14,6 @@ -
diff --git a/addons/mail/static/src/components/thread_view/tests/thread_view_tests.js b/addons/mail/static/src/components/thread_view/tests/thread_view_tests.js index 46c0969d285..5ce814ca89f 100644 --- a/addons/mail/static/src/components/thread_view/tests/thread_view_tests.js +++ b/addons/mail/static/src/components/thread_view/tests/thread_view_tests.js @@ -986,7 +986,7 @@ QUnit.test("delete all attachments of message without content should no longer d res_id: 11, } ); - const { createThreadViewComponent } = await this.start(); + const { createThreadViewComponent } = await this.start({ hasDialog: true }); const threadViewer = this.messaging.models['ThreadViewer'].create({ hasThreadView: true, qunitTest: insertAndReplace(), @@ -1046,7 +1046,7 @@ QUnit.test('delete all attachments of a message with some text content should st res_id: 11, }, ); - const { createThreadViewComponent } = await this.start(); + const { createThreadViewComponent } = await this.start({ hasDialog: true }); const threadViewer = this.messaging.models['ThreadViewer'].create({ hasThreadView: true, qunitTest: insertAndReplace(), @@ -1113,7 +1113,7 @@ QUnit.test('delete all attachments of a message with tracking fields should stil new_value: "New name", old_value: "Old name", }); - const { createThreadViewComponent } = await this.start(); + const { createThreadViewComponent } = await this.start({ hasDialog: true }); const threadViewer = this.messaging.models['ThreadViewer'].create({ hasThreadView: true, qunitTest: insertAndReplace(), diff --git a/addons/mail/static/src/models/attachment_box_view/attachment_box_view.js b/addons/mail/static/src/models/attachment_box_view/attachment_box_view.js index 7d6b2c9153b..57c2dc3275c 100644 --- a/addons/mail/static/src/models/attachment_box_view/attachment_box_view.js +++ b/addons/mail/static/src/models/attachment_box_view/attachment_box_view.js @@ -8,13 +8,6 @@ registerModel({ name: 'AttachmentBoxView', identifyingFields: ['chatter'], recordMethods: { - /** - * Handles attachment removed event. - */ - onAttachmentRemoved() { - // FIXME Could be changed by spying attachments count (task-2252858) - this.component.trigger('o-attachments-changed'); - }, /** * Handles click on the "add attachment" button. */ diff --git a/addons/mail/static/src/models/attachment_card/attachment_card.js b/addons/mail/static/src/models/attachment_card/attachment_card.js index 4563eca1dc5..a145b1eac15 100644 --- a/addons/mail/static/src/models/attachment_card/attachment_card.js +++ b/addons/mail/static/src/models/attachment_card/attachment_card.js @@ -34,18 +34,9 @@ registerModel({ this.component.trigger('o-attachment-removed', { attachmentLocalId: this.attachment.localId }); this.attachment.remove(); } else { - this.update({ hasDeleteConfirmDialog: true }); + this.update({ attachmentDeleteConfirmDialog: insertAndReplace() }); } }, - /** - * Synchronizes the `hasDeleteConfirmDialog` when the dialog is closed. - */ - onDeleteConfirmDialogClosed() { - if (!this.exists()) { - return; - } - this.update({ hasDeleteConfirmDialog: false }); - }, }, fields: { /** @@ -55,6 +46,10 @@ registerModel({ readonly: true, required: true, }), + attachmentDeleteConfirmDialog: one('Dialog', { + inverse: 'attachmentCardOwnerAsAttachmentDeleteConfirm', + isCausal: true, + }), /** * States the attachmentList displaying this card. */ @@ -67,11 +62,5 @@ registerModel({ * States the OWL component of this attachment card. */ component: attr(), - /** - * Determines the status of the delete confirm dialog (open/closed). - */ - hasDeleteConfirmDialog: attr({ - default: false, - }), }, }); diff --git a/addons/mail/static/src/models/attachment_delete_confirm_view/attachment_delete_confirm_view.js b/addons/mail/static/src/models/attachment_delete_confirm_view/attachment_delete_confirm_view.js new file mode 100644 index 00000000000..f4c5f290ad2 --- /dev/null +++ b/addons/mail/static/src/models/attachment_delete_confirm_view/attachment_delete_confirm_view.js @@ -0,0 +1,90 @@ +/** @odoo-module **/ + +import { registerModel } from '@mail/model/model_core'; +import { attr, one } from '@mail/model/model_field'; +import { clear, replace } from '@mail/model/model_field_command'; + +registerModel({ + name: 'AttachmentDeleteConfirmView', + identifyingFields: ['dialogOwner'], + recordMethods: { + /** + * Returns whether the given html element is inside this attachment delete confirm view. + * + * @param {Element} element + * @returns {boolean} + */ + containsElement(element) { + return Boolean(this.component && this.component.root.el && this.component.root.el.contains(element)); + }, + onClickCancel() { + this.dialogOwner.delete(); + }, + async onClickOk() { + await this.attachment.remove(); + if (this.chatter && this.chatter.component) { + this.chatter.component.trigger('o-attachments-changed'); + } + }, + /** + * @private + * @returns {FieldCommand} + */ + _computeAttachment() { + if (this.dialogOwner && this.dialogOwner.attachmentCardOwnerAsAttachmentDeleteConfirm) { + return replace(this.dialogOwner.attachmentCardOwnerAsAttachmentDeleteConfirm.attachment); + } + if (this.dialogOwner && this.dialogOwner.attachmentImageOwnerAsAttachmentDeleteConfirm) { + return replace(this.dialogOwner.attachmentImageOwnerAsAttachmentDeleteConfirm.attachment); + } + return clear(); + }, + /** + * @private + * @returns {string} + */ + _computeBody() { + return _.str.sprintf(this.env._t(`Do you really want to delete "%s"?`), this.attachment.displayName); + }, + /** + * @private + * @returns {FieldCommand} + */ + _computeChatter() { + if ( + this.dialogOwner.attachmentCardOwnerAsAttachmentDeleteConfirm && + this.dialogOwner.attachmentCardOwnerAsAttachmentDeleteConfirm.attachmentList.attachmentBoxViewOwner && + this.dialogOwner.attachmentCardOwnerAsAttachmentDeleteConfirm.attachmentList.attachmentBoxViewOwner.chatter + ) { + return replace(this.dialogOwner.attachmentCardOwnerAsAttachmentDeleteConfirm.attachmentList.attachmentBoxViewOwner.chatter); + } + if ( + this.dialogOwner.attachmentImageOwnerAsAttachmentDeleteConfirm && + this.dialogOwner.attachmentImageOwnerAsAttachmentDeleteConfirm.attachmentList.attachmentBoxViewOwner && + this.dialogOwner.attachmentImageOwnerAsAttachmentDeleteConfirm.attachmentList.attachmentBoxViewOwner.chatter + ) { + return replace(this.dialogOwner.attachmentImageOwnerAsAttachmentDeleteConfirm.attachmentList.attachmentBoxViewOwner.chatter); + } + return clear(); + }, + }, + fields: { + attachment: one('Attachment', { + compute: '_computeAttachment', + readonly: true, + required: true, + }), + body: attr({ + compute: '_computeBody', + }), + chatter: one('Chatter', { + compute: '_computeChatter', + }), + component: attr(), + dialogOwner: one('Dialog', { + inverse: 'attachmentDeleteConfirmView', + readonly: true, + required: true, + }), + }, +}); diff --git a/addons/mail/static/src/models/attachment_image/attachment_image.js b/addons/mail/static/src/models/attachment_image/attachment_image.js index 329c4577cdd..90a7fd7fd20 100644 --- a/addons/mail/static/src/models/attachment_image/attachment_image.js +++ b/addons/mail/static/src/models/attachment_image/attachment_image.js @@ -34,18 +34,9 @@ registerModel({ this.component.trigger('o-attachment-removed', { attachmentLocalId: this.attachment.localId }); this.attachment.remove(); } else { - this.update({ hasDeleteConfirmDialog: true }); + this.update({ attachmentDeleteConfirmDialog: insertAndReplace() }); } }, - /** - * Synchronize the `hasDeleteConfirmDialog` when the dialog is closed. - */ - onDeleteConfirmDialogClosed() { - if (!this.exists()) { - return; - } - this.update({ hasDeleteConfirmDialog: false }); - }, /** * @private * @returns {number} @@ -97,6 +88,10 @@ registerModel({ readonly: true, required: true, }), + attachmentDeleteConfirmDialog: one('Dialog', { + inverse: 'attachmentImageOwnerAsAttachmentDeleteConfirm', + isCausal: true, + }), /** * States the attachmentList displaying this attachment image. */ @@ -109,12 +104,6 @@ registerModel({ * States the OWL component of this attachment image. */ component: attr(), - /** - * Determines the status of the delete confirm dialog (open/closed). - */ - hasDeleteConfirmDialog: attr({ - default: false, - }), /** * Determines the max height of this attachment image in px. */ diff --git a/addons/mail/static/src/models/composer_view/composer_view.js b/addons/mail/static/src/models/composer_view/composer_view.js index c4e80c12891..bc2712c5cde 100644 --- a/addons/mail/static/src/models/composer_view/composer_view.js +++ b/addons/mail/static/src/models/composer_view/composer_view.js @@ -459,7 +459,7 @@ registerModel({ async updateMessage() { const composer = this.composer; if (!composer.textInputContent) { - this.messageViewInEditing.messageActionList.update({ showDeleteConfirm: true }); + this.messageViewInEditing.messageActionList.update({ deleteConfirmDialog: insertAndReplace() }); return; } const escapedAndCompactContent = escapeAndCompactTextContent(composer.textInputContent); diff --git a/addons/mail/static/src/models/delete_message_confirm_view/delete_message_confirm_view.js b/addons/mail/static/src/models/delete_message_confirm_view/delete_message_confirm_view.js new file mode 100644 index 00000000000..adb7b9127ab --- /dev/null +++ b/addons/mail/static/src/models/delete_message_confirm_view/delete_message_confirm_view.js @@ -0,0 +1,68 @@ +/** @odoo-module **/ + +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'; + +registerModel({ + name: 'DeleteMessageConfirmView', + identifyingFields: ['dialogOwner'], + recordMethods: { + /** + * Returns whether the given html element is inside this delete message confirm view. + * + * @param {Element} element + * @returns {boolean} + */ + containsElement(element) { + return Boolean(this.component && this.component.root.el && this.component.root.el.contains(element)); + }, + onClickCancel() { + this.dialogOwner.delete(); + }, + onClickDelete() { + this.message.updateContent({ + attachment_ids: [], + body: '', + }); + }, + /** + * @private + * @returns {FieldCommand} + */ + _computeMessage() { + return replace(this.dialogOwner.messageActionListOwnerAsDeleteConfirm.message); + }, + /** + * @private + * @returns {MessageView} + */ + _computeMessageView() { + return this.message ? insertAndReplace({ message: replace(this.message) }) : clear(); + }, + }, + fields: { + component: attr(), + dialogOwner: one('Dialog', { + inverse: 'deleteMessageConfirmView', + readonly: true, + required: true, + }), + message: one('Message', { + compute: '_computeMessage', + readonly: true, + required: true, + }), + /** + * Determines the message view that this delete message confirm view + * will use to display this message. + */ + messageView: one('MessageView', { + compute: '_computeMessageView', + inverse: 'deleteMessageConfirmViewOwner', + isCausal: true, + readonly: true, + required: true, + }), + }, +}); diff --git a/addons/mail/static/src/models/dialog/dialog.js b/addons/mail/static/src/models/dialog/dialog.js index 8671b6afa70..ba0a94ed2e3 100644 --- a/addons/mail/static/src/models/dialog/dialog.js +++ b/addons/mail/static/src/models/dialog/dialog.js @@ -7,8 +7,11 @@ import { clear, insertAndReplace, replace } from '@mail/model/model_field_comman registerModel({ name: 'Dialog', identifyingFields: [[ + 'attachmentCardOwnerAsAttachmentDeleteConfirm', + 'attachmentImageOwnerAsAttachmentDeleteConfirm', 'attachmentListOwnerAsAttachmentView', 'followerOwnerAsSubtypeList', + 'messageActionListOwnerAsDeleteConfirm', ]], recordMethods: { /** @@ -18,6 +21,19 @@ registerModel({ hasElementInContent(element) { return Boolean(this.record && this.record.containsElement(element)); }, + /** + * @private + * @returns {FieldCommand} + */ + _computeAttachmentDeleteConfirmView() { + if (this.attachmentCardOwnerAsAttachmentDeleteConfirm) { + return insertAndReplace(); + } + if (this.attachmentImageOwnerAsAttachmentDeleteConfirm) { + return insertAndReplace(); + } + return clear(); + }, /** * @private * @returns {FieldCommand} @@ -28,6 +44,29 @@ registerModel({ } return clear(); }, + /** + * @private + * @returns {number} + */ + _computeBackgroundOpacity() { + if (this.attachmentViewer) { + return 0.7; + } + return 0.5; + }, + /** + * @private + * @returns {string} + */ + _computeComponentClassName() { + if (this.attachmentDeleteConfirmView) { + return 'o_Dialog_componentMediumSize align-self-start mt-5'; + } + if (this.deleteMessageConfirmView) { + return 'o_Dialog_componentLargeSize align-self-start mt-5'; + } + return ''; + }, /** * @private * @returns {string|FieldCommand} @@ -36,20 +75,30 @@ registerModel({ if (this.attachmentViewer) { return 'AttachmentViewer'; } + if (this.attachmentDeleteConfirmView) { + return 'AttachmentDeleteConfirm'; + } + if (this.deleteMessageConfirmView) { + return 'DeleteMessageConfirm'; + } if (this.followerSubtypeList) { return 'FollowerSubtypeList'; } return clear(); }, + /** + * @private + * @returns {FieldCommand} + */ + _computeDeleteMessageConfirmView() { + return this.messageActionListOwnerAsDeleteConfirm ? insertAndReplace() : clear(); + }, /** * @private * @returns {FieldCommand} */ _computeFollowerSubtypeList() { - if (this.followerOwnerAsSubtypeList) { - return insertAndReplace(); - } - return clear(); + return this.followerOwnerAsSubtypeList ? insertAndReplace() : clear(); }, /** /** @@ -84,12 +133,38 @@ registerModel({ if (this.attachmentViewer) { return replace(this.attachmentViewer); } + if (this.attachmentDeleteConfirmView) { + return replace(this.attachmentDeleteConfirmView); + } + if (this.deleteMessageConfirmView) { + return replace(this.deleteMessageConfirmView); + } if (this.followerSubtypeList) { return replace(this.followerSubtypeList); } }, + /** + * @private + * @returns {string} + */ + _computeStyle() { + return `background-color: rgba(0, 0, 0, ${this.backgroundOpacity});`; + }, }, fields: { + attachmentCardOwnerAsAttachmentDeleteConfirm: one('AttachmentCard', { + inverse: 'attachmentDeleteConfirmDialog', + readonly: true, + }), + attachmentDeleteConfirmView: one('AttachmentDeleteConfirmView', { + compute: '_computeAttachmentDeleteConfirmView', + inverse: 'dialogOwner', + isCausal: true, + }), + attachmentImageOwnerAsAttachmentDeleteConfirm: one('AttachmentImage', { + inverse: 'attachmentDeleteConfirmDialog', + readonly: true, + }), attachmentListOwnerAsAttachmentView: one('AttachmentList', { inverse: 'attachmentListViewDialog', readonly: true, @@ -99,10 +174,21 @@ registerModel({ inverse: 'dialogOwner', isCausal: true, }), + backgroundOpacity: attr({ + compute: '_computeBackgroundOpacity', + }), + componentClassName: attr({ + compute: '_computeComponentClassName', + }), componentName: attr({ compute: '_computeComponentName', required: true, }), + deleteMessageConfirmView: one('DeleteMessageConfirmView', { + compute: '_computeDeleteMessageConfirmView', + inverse: 'dialogOwner', + isCausal: true, + }), followerOwnerAsSubtypeList: one('Follower', { inverse: 'followerSubtypeListDialog', readonly: true, @@ -121,6 +207,10 @@ registerModel({ inverse: 'dialogs', readonly: true, }), + messageActionListOwnerAsDeleteConfirm: one('MessageActionList', { + inverse: 'deleteConfirmDialog', + readonly: true, + }), /** * Content of dialog that is directly linked to a record that models * a UI component, such as AttachmentViewer. These records must be @@ -132,5 +222,8 @@ registerModel({ readonly: true, required: true, }), + style: attr({ + compute: '_computeStyle', + }), }, }); diff --git a/addons/mail/static/src/models/message_action_list/message_action_list.js b/addons/mail/static/src/models/message_action_list/message_action_list.js index 259fac9c0bd..bbeb3196f4a 100644 --- a/addons/mail/static/src/models/message_action_list/message_action_list.js +++ b/addons/mail/static/src/models/message_action_list/message_action_list.js @@ -16,22 +16,12 @@ registerModel({ onClick(ev) { markEventHandled(ev, 'MessageActionList.Click'); }, - /** - * @private - * @param {MouseEvent} ev - */ - onClickConfirmDelete(ev) { - this.message.updateContent({ - body: '', - attachment_ids: [], - }); - }, /** * @private * @param {MouseEvent} ev */ onClickDelete(ev) { - this.update({ showDeleteConfirm: true }); + this.update({ deleteConfirmDialog: insertAndReplace() }); }, /** * @private @@ -82,13 +72,6 @@ registerModel({ onClickToggleStar(ev) { this.message.toggleStar(); }, - /** - * @private - * @param {CustomEvent} ev - */ - onDeleteConfirmDialogClosed(ev) { - this.update({ showDeleteConfirm: false }); - }, /** * @private * @returns {boolean} @@ -114,21 +97,16 @@ registerModel({ ) ); }, - /** - * @private - * @returns {MessageView} - */ - _computeMessageViewForDelete() { - return this.message - ? insertAndReplace({ message: replace(this.message) }) - : clear(); - }, }, fields: { /** * States the reference to the reaction action in the component. */ actionReactionRef: attr(), + deleteConfirmDialog: one('Dialog', { + inverse: 'messageActionListOwnerAsDeleteConfirm', + isCausal: true, + }), /** * Determines whether this message action list has mark as read icon. */ @@ -155,15 +133,6 @@ registerModel({ readonly: true, required: true, }), - /** - * Determines the message view that this message action list will use to - * display this message in this delete confirmation dialog. - */ - messageViewForDelete: one('MessageView', { - compute: '_computeMessageViewForDelete', - inverse: 'messageActionListWithDelete', - isCausal: true, - }), /** * Determines the reaction popover that is active on this message action list. */ @@ -171,11 +140,5 @@ registerModel({ inverse: 'messageActionListOwnerAsReaction', isCausal: true, }), - /** - * Determines whether to show the message delete-confirm dialog. - */ - showDeleteConfirm: attr({ - default: false, - }), }, }); diff --git a/addons/mail/static/src/models/message_view/message_view.js b/addons/mail/static/src/models/message_view/message_view.js index c6bdc2fa09c..4d1ab22dc0c 100644 --- a/addons/mail/static/src/models/message_view/message_view.js +++ b/addons/mail/static/src/models/message_view/message_view.js @@ -3,10 +3,11 @@ 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 { markEventHandled } from '@mail/utils/utils'; registerModel({ name: 'MessageView', - identifyingFields: [['threadView', 'messageActionListWithDelete'], 'message'], + identifyingFields: [['threadView', 'deleteMessageConfirmViewOwner'], 'message'], recordMethods: { /** * Briefly highlights the message. @@ -20,6 +21,13 @@ registerModel({ }, 2000), }); }, + /** + * @param {MouseEvent} ev + */ + onClickFailure(ev) { + markEventHandled(ev, 'Message.ClickFailure'); + this.message.openResendAction(); + }, onComponentUpdate() { if (!this.exists()) { return; @@ -110,9 +118,7 @@ registerModel({ * @returns {FieldCommand} */ _computeMessageActionList() { - return (!this.messageActionListWithDelete) - ? insertAndReplace() - : clear(); + return this.deleteMessageConfirmViewOwner ? clear() : insertAndReplace(); }, /** * @private @@ -153,6 +159,14 @@ registerModel({ inverse: 'messageViewInEditing', isCausal: true, }), + /** + * States the delete message confirm view that is displaying this + * message view. + */ + deleteMessageConfirmViewOwner: one('DeleteMessageConfirmView', { + inverse: 'messageView', + readonly: true, + }), /** * Determines whether this message view should be highlighted at next * render. Scrolls into view and briefly highlights it. @@ -189,15 +203,6 @@ registerModel({ isCausal: true, readonly: true, }), - /** - * States the message action list that is displaying this message view - * in its delete confirmation view. - */ - messageActionListWithDelete: one('MessageActionList', { - inverse: 'messageViewForDelete', - isCausal: true, - readonly: true, - }), /** * Determines the message that is displayed by this message view. */ diff --git a/addons/snailmail/static/src/components/message/message.js b/addons/snailmail/static/src/components/message/message.js deleted file mode 100644 index ad7630b5c61..00000000000 --- a/addons/snailmail/static/src/components/message/message.js +++ /dev/null @@ -1,76 +0,0 @@ -/** @odoo-module **/ - -import { Message } from '@mail/components/message/message'; - -import { patch } from 'web.utils'; - -const { useState } = owl; - -patch(Message.prototype, 'snailmail/static/src/components/message/message.js', { - /** - * @override - */ - setup() { - this._super(); - this._onDialogClosedSnailmailError = this._onDialogClosedSnailmailError.bind(this); - this.snailmailState = useState({ - // Determine if the error dialog is displayed. - hasDialog: false, - }); - }, - - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- - - /** - * @override - */ - _onClickFailure() { - if (this.messageView.message.message_type === 'snailmail') { - /** - * Messages from snailmail are considered to have at most one - * notification. The failure type of the whole message is considered - * to be the same as the one from that first notification, and the - * click action will depend on it. - */ - switch (this.messageView.message.notifications[0].failure_type) { - case 'sn_credit': - // URL only used in this component, not received at init - this.messaging.fetchSnailmailCreditsUrl(); - this.snailmailState.hasDialog = true; - break; - case 'sn_error': - this.snailmailState.hasDialog = true; - break; - case 'sn_fields': - this.messageView.message.openMissingFieldsLetterAction(); - break; - case 'sn_format': - this.messageView.message.openFormatLetterAction(); - break; - case 'sn_price': - this.snailmailState.hasDialog = true; - break; - case 'sn_trial': - // URL only used in this component, not received at init - this.messaging.fetchSnailmailCreditsUrlTrial(); - this.snailmailState.hasDialog = true; - break; - } - } else { - this._super(...arguments); - } - }, - - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- - - /** - * @private - */ - _onDialogClosedSnailmailError() { - this.snailmailState.hasDialog = false; - }, -}); diff --git a/addons/snailmail/static/src/components/message/message.xml b/addons/snailmail/static/src/components/message/message.xml index 46dafd2bb65..e1537fd6669 100644 --- a/addons/snailmail/static/src/components/message/message.xml +++ b/addons/snailmail/static/src/components/message/message.xml @@ -16,12 +16,6 @@ $0 - - - - - -