summaryrefslogtreecommitdiff
path: root/addons/mail/static/src/components
diff options
context:
space:
mode:
authorXavier Dubuc <xdu@odoo.com>2020-08-18 12:24:10 +0000
committerAlexandre Kühn <aku@odoo.com>2020-08-21 12:57:44 +0000
commit0263acee7f355e7367686a461c21f28ea34cfa9a (patch)
tree5f445f8b559c46263d438442b505f629d9545015 /addons/mail/static/src/components
parentf25b730b2f548616d62cf8f30907103116e8c0fd (diff)
[FIX] mail: prevent composer to send message if pending uploads
task-2317862 closes odoo/odoo#56303 X-original-commit: 3b5cd048f1dfa18869e95b173b4232b4bb189025 Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
Diffstat (limited to 'addons/mail/static/src/components')
-rw-r--r--addons/mail/static/src/components/composer/composer.js18
-rw-r--r--addons/mail/static/src/components/composer/composer.xml2
-rw-r--r--addons/mail/static/src/components/composer/composer_tests.js143
3 files changed, 156 insertions, 7 deletions
diff --git a/addons/mail/static/src/components/composer/composer.js b/addons/mail/static/src/components/composer/composer.js
index 5c3968a0fae..afb7d811eae 100644
--- a/addons/mail/static/src/components/composer/composer.js
+++ b/addons/mail/static/src/components/composer/composer.js
@@ -175,9 +175,21 @@ class Composer extends Component {
/**
* Post a message in the composer on related thread.
*
+ * Posting of the message could be aborted if it cannot be posted like if there are attachments
+ * currently uploading or if there is no text content and no attachments.
+ *
* @private
*/
async _postMessage() {
+ if (!this.composer.canPostMessage) {
+ if (this.composer.hasUploadingAttachment) {
+ this.env.services['notification'].notify({
+ message: this.env._t("Please wait while the file is uploading."),
+ type: 'warning',
+ });
+ }
+ return;
+ }
// TODO: take suggested recipients into account (task-2283356)
await this.composer.postMessage();
// TODO: we might need to remove trigger and use the store to wait for the post rpc to be done
@@ -246,9 +258,6 @@ class Composer extends Component {
* @private
*/
_onClickSend() {
- if (!this.composer.canPostMessage) {
- return;
- }
this._postMessage();
}
@@ -335,9 +344,6 @@ class Composer extends Component {
* @private
*/
_onTextInputKeydownEnter() {
- if (!this.composer.canPostMessage) {
- return;
- }
this._postMessage();
}
diff --git a/addons/mail/static/src/components/composer/composer.xml b/addons/mail/static/src/components/composer/composer.xml
index 5a7a2e72345..30053cdd0f8 100644
--- a/addons/mail/static/src/components/composer/composer.xml
+++ b/addons/mail/static/src/components/composer/composer.xml
@@ -155,7 +155,7 @@
'o-composer-is-compact': props.isCompact,
'o-has-current-partner-avatar': props.hasCurrentPartnerAvatar,
}"
- t-att-disabled="(!composer.textInputContent and composer.attachments.length === 0) ? 'disabled' : ''"
+ t-att-disabled="!composer.canPostMessage ? 'disabled' : ''"
type="button"
t-on-click="_onClickSend"
>
diff --git a/addons/mail/static/src/components/composer/composer_tests.js b/addons/mail/static/src/components/composer/composer_tests.js
index 527003b6dec..8e07affcccb 100644
--- a/addons/mail/static/src/components/composer/composer_tests.js
+++ b/addons/mail/static/src/components/composer/composer_tests.js
@@ -21,6 +21,7 @@ const {
createFile,
inputFiles,
},
+ makeTestPromise,
} = require('web.test_utils');
QUnit.module('mail', {}, function () {
@@ -886,6 +887,148 @@ QUnit.test('current partner notify is typing again to other members every 50s of
);
});
+QUnit.test('composer: send button is disabled if attachment upload is not finished', async function (assert) {
+ assert.expect(8);
+
+ const attachmentUploadedPromise = makeTestPromise();
+ await this.start({
+ async mockFetch(resource, init) {
+ const res = this._super(...arguments);
+ if (resource === '/web/binary/upload_attachment') {
+ await attachmentUploadedPromise;
+ }
+ return res;
+ }
+ });
+ const composer = this.env.models['mail.composer'].create();
+ await this.createComposerComponent(composer);
+ const file = await createFile({
+ content: 'hello, world',
+ contentType: 'text/plain',
+ name: 'text.txt',
+ });
+ await afterNextRender(() =>
+ inputFiles(
+ document.querySelector('.o_FileUploader_input'),
+ [file]
+ )
+ );
+ assert.containsOnce(
+ document.body,
+ '.o_Attachment',
+ "should have an attachment after a file has been input"
+ );
+ assert.containsOnce(
+ document.body,
+ '.o_Attachment.o-temporary',
+ "attachment displayed is being uploaded"
+ );
+ assert.containsOnce(
+ document.body,
+ '.o_Composer_buttonSend',
+ "composer send button should be displayed"
+ );
+ assert.ok(
+ !!document.querySelector('.o_Composer_buttonSend').attributes.disabled,
+ "composer send button should be disabled as attachment is not yet uploaded"
+ );
+
+ // simulates attachment finishes uploading
+ await afterNextRender(() => attachmentUploadedPromise.resolve());
+ assert.containsOnce(
+ document.body,
+ '.o_Attachment',
+ "should have only one attachment"
+ );
+ assert.containsNone(
+ document.body,
+ '.o_Attachment.o-temporary',
+ "attachment displayed should be uploaded"
+ );
+ assert.containsOnce(
+ document.body,
+ '.o_Composer_buttonSend',
+ "composer send button should still be present"
+ );
+ assert.ok(
+ !document.querySelector('.o_Composer_buttonSend').attributes.disabled,
+ "composer send button should be enabled as attachment is now uploaded"
+ );
+});
+
+QUnit.test('warning when attempting to post message when attachments are still uploading', async function (assert) {
+ assert.expect(7);
+
+ await this.start({
+ async mockFetch(resource, init) {
+ const res = this._super(...arguments);
+ if (resource === '/web/binary/upload_attachment') {
+ // simulates attachment is never finished uploading
+ await new Promise(() => {});
+ }
+ return res;
+ },
+ services: {
+ notification: {
+ notify(params) {
+ assert.strictEqual(
+ params.message,
+ "Please wait while the file is uploading.",
+ "notification content should be about the uploading file"
+ );
+ assert.strictEqual(
+ params.type,
+ 'warning',
+ "notification should be a warning"
+ );
+ assert.step('notification');
+ }
+ }
+ },
+ });
+ const thread = this.env.models['mail.thread'].create({
+ composer: [['create', { isLog: false }]],
+ id: 20,
+ model: 'res.partner',
+ });
+ await this.createComposerComponent(thread.composer);
+ const file = await createFile({
+ content: 'hello, world',
+ contentType: 'text/plain',
+ name: 'text.txt',
+ });
+ await afterNextRender(() =>
+ inputFiles(
+ document.querySelector('.o_FileUploader_input'),
+ [file]
+ )
+ );
+ assert.containsOnce(
+ document.body,
+ '.o_Attachment',
+ "should have only one attachment"
+ );
+ assert.containsOnce(
+ document.body,
+ '.o_Attachment.o-temporary',
+ "attachment displayed is being uploaded"
+ );
+ assert.containsOnce(
+ document.body,
+ '.o_Composer_buttonSend',
+ "composer send button should be displayed"
+ );
+
+ // Try to send message
+ document
+ .querySelector(`.o_ComposerTextInput_textarea`)
+ .dispatchEvent(new window.KeyboardEvent('keydown', { key: 'Enter' }));
+ assert.verifySteps(
+ ['notification'],
+ "should have triggered a notification for inability to post message at the moment (some attachments are still being uploaded)"
+ );
+});
+
});
});
});