summaryrefslogtreecommitdiff
path: root/addons/mail
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2019-04-12 13:37:44 +0200
committerChristophe Simonis <chs@odoo.com>2019-04-12 13:37:44 +0200
commit0a09a4d8a819ef06db47e798f0465e500004e4c1 (patch)
treeb9d66d60a1e9b5ff6030be62fff89df410b744ee /addons/mail
parentdb97bb7f1136dc3ebde9924b79364a698a63765d (diff)
parent120359bf0c98191051ac19ae2e5fde53ca7d2ae5 (diff)
[MERGE] forward port branch saas-12.3 up to 120359bf0c9
Diffstat (limited to 'addons/mail')
-rw-r--r--addons/mail/models/ir_attachment.py7
-rw-r--r--addons/mail/models/mail_mail.py18
-rw-r--r--addons/mail/models/mail_message.py4
-rw-r--r--addons/mail/models/mail_thread.py2
-rw-r--r--addons/mail/static/src/js/chatter.js4
-rw-r--r--addons/mail/static/src/js/document_viewer.js5
-rw-r--r--addons/mail/static/src/scss/chatter.scss21
-rw-r--r--addons/mail/static/src/scss/composer.scss3
-rw-r--r--addons/mail/static/src/xml/thread.xml20
-rw-r--r--addons/mail/static/tests/document_viewer_tests.js19
10 files changed, 72 insertions, 31 deletions
diff --git a/addons/mail/models/ir_attachment.py b/addons/mail/models/ir_attachment.py
index 31e59d680c9..7273145096d 100644
--- a/addons/mail/models/ir_attachment.py
+++ b/addons/mail/models/ir_attachment.py
@@ -13,9 +13,9 @@ class IrAttachment(models.Model):
"""
super(IrAttachment, self)._post_add_create()
for record in self:
- record.register_as_main_attachment()
+ record.register_as_main_attachment(force=False)
- def register_as_main_attachment(self):
+ def register_as_main_attachment(self, force=True):
""" Registers this attachment as the main one of the model it is
attached to.
"""
@@ -24,4 +24,5 @@ class IrAttachment(models.Model):
# message_main_attachment_id field can be empty, that's why we compare to False;
# we are just checking that it exists on the model before writing it
if related_record and hasattr(related_record, 'message_main_attachment_id'):
- related_record.message_main_attachment_id = self
+ if force or not related_record.message_main_attachment_id:
+ related_record.message_main_attachment_id = self
diff --git a/addons/mail/models/mail_mail.py b/addons/mail/models/mail_mail.py
index 7aff20cf59e..a2ba820656f 100644
--- a/addons/mail/models/mail_mail.py
+++ b/addons/mail/models/mail_mail.py
@@ -5,6 +5,7 @@ import base64
import datetime
import logging
import psycopg2
+import smtplib
import threading
import re
@@ -162,14 +163,14 @@ class MailMail(models.Model):
failed = self.env['mail.notification']
if failure_type:
failed = notifications.filtered(lambda notif: notif.res_partner_id not in success_pids)
- failed.write({
+ failed.sudo().write({
'email_status': 'exception',
'failure_type': failure_type,
'failure_reason': failure_reason,
})
messages = notifications.mapped('mail_message_id').filtered(lambda m: m.res_id and m.model)
messages._notify_failure_update() # notify user that we have a failure
- (notifications - failed).write({
+ (notifications - failed).sudo().write({
'email_status': 'sent',
})
if not failure_type or failure_type == 'RECIPIENT': # if we have another error, we want to keep the mail.
@@ -338,7 +339,7 @@ class MailMail(models.Model):
])
if notifs:
notif_msg = _('Error without exception. Probably due do concurrent access update of notification records. Please see with an administrator.')
- notifs.write({
+ notifs.sudo().write({
'email_status': 'exception',
'failure_type': 'UNKNOWN',
'failure_reason': notif_msg,
@@ -394,11 +395,12 @@ class MailMail(models.Model):
mail.id, mail.message_id)
# mail status will stay on ongoing since transaction will be rollback
raise
- except psycopg2.Error:
- # If an error with the database occurs, chances are that the cursor is unusable.
- # This will lead to an `psycopg2.InternalError` being raised when trying to write
- # `state`, shadowing the original exception and forbid a retry on concurrent
- # update. Let's bubble it.
+ except (psycopg2.Error, smtplib.SMTPServerDisconnected):
+ # If an error with the database or SMTP session occurs, chances are that the cursor
+ # or SMTP session are unusable, causing further errors when trying to save the state.
+ _logger.exception(
+ 'Exception while processing mail with ID %r and Msg-Id %r.',
+ mail.id, mail.message_id)
raise
except Exception as e:
failure_reason = tools.ustr(e)
diff --git a/addons/mail/models/mail_message.py b/addons/mail/models/mail_message.py
index e228f7c4062..e2ebb16c69e 100644
--- a/addons/mail/models/mail_message.py
+++ b/addons/mail/models/mail_message.py
@@ -154,8 +154,8 @@ class Message(models.Model):
@api.multi
def _search_has_error(self, operator, operand):
if operator == '=' and operand:
- return ['&', ('notification_ids.email_status', 'in', ('bounce', 'exception')), ('author_id', '=', self.env.user.partner_id.id)]
- return ['!', '&', ('notification_ids.email_status', 'in', ('bounce', 'exception')), ('author_id', '=', self.env.user.partner_id.id)] # this wont work and will be equivalent to "not in" beacause of orm restrictions. Dont use "has_error = False"
+ return [('notification_ids.email_status', 'in', ('bounce', 'exception'))]
+ return ['!', ('notification_ids.email_status', 'in', ('bounce', 'exception'))] # this wont work and will be equivalent to "not in" beacause of orm restrictions. Dont use "has_error = False"
@api.depends('starred_partner_ids')
def _get_starred(self):
diff --git a/addons/mail/models/mail_thread.py b/addons/mail/models/mail_thread.py
index 127b7f7d609..81f1dc0510b 100644
--- a/addons/mail/models/mail_thread.py
+++ b/addons/mail/models/mail_thread.py
@@ -237,7 +237,7 @@ class MailThread(models.AbstractModel):
@api.model
def _search_message_has_error(self, operator, operand):
- return [('message_ids.has_error', operator, operand)]
+ return ['&', ('message_ids.has_error', operator, operand), ('message_ids.author_id', '=', self.env.user.partner_id.id)]
@api.multi
def _compute_message_attachment_count(self):
diff --git a/addons/mail/static/src/js/chatter.js b/addons/mail/static/src/js/chatter.js
index bc5d18a4150..968242ffe6a 100644
--- a/addons/mail/static/src/js/chatter.js
+++ b/addons/mail/static/src/js/chatter.js
@@ -81,6 +81,7 @@ var Chatter = Widget.extend({
var nodeOptions = fieldsInfo[mailFields.mail_thread].options || {};
this.hasLogButton = options.display_log_button || nodeOptions.display_log_button;
this.postRefresh = nodeOptions.post_refresh || 'never';
+ this.reloadOnUploadAttachment = this.postRefresh === 'always';
}
},
/**
@@ -577,6 +578,9 @@ var Chatter = Widget.extend({
* @private
*/
_onReloadAttachmentBox: function () {
+ if (this.reloadOnUploadAttachment) {
+ this.trigger_up('reload');
+ }
this._reloadAttachmentBox();
},
/**
diff --git a/addons/mail/static/src/js/document_viewer.js b/addons/mail/static/src/js/document_viewer.js
index fc084b48204..be7dfeb9115 100644
--- a/addons/mail/static/src/js/document_viewer.js
+++ b/addons/mail/static/src/js/document_viewer.js
@@ -44,11 +44,10 @@ var DocumentViewer = Widget.extend({
this._super.apply(this, arguments);
this.attachment = _.filter(attachments, function (attachment) {
var match = attachment.type === 'url' ? attachment.url.match("(youtu|.png|.jpg|.gif)") : attachment.mimetype.match("(image|video|application/pdf|text)");
-
if (match) {
- attachment.type = match[1];
+ attachment.fileType = match[1];
if (match[1].match("(.png|.jpg|.gif)")) {
- attachment.type = 'image';
+ attachment.fileType = 'image';
}
if (match[1] === 'youtu') {
var youtube_array = attachment.url.split('/');
diff --git a/addons/mail/static/src/scss/chatter.scss b/addons/mail/static/src/scss/chatter.scss
index b670e5b92d0..5b503966706 100644
--- a/addons/mail/static/src/scss/chatter.scss
+++ b/addons/mail/static/src/scss/chatter.scss
@@ -21,11 +21,11 @@
position: relative;
float: right;
flex: 1 1 auto;
+ height: $o-statusbar-height;
.o_chatter_button_attachment {
- height: $o-statusbar-height - 2px;
+ height: $o-statusbar-height;
float: right;
- padding: 0px;
margin-right: 25px;
.fa-paperclip, .o_chatter_attachment_button_count {
@@ -33,15 +33,20 @@
}
}
.o_followers {
- height: $o-statusbar-height + 1;
+ height: $o-statusbar-height;
border-bottom: 1px solid transparent;
flex: 0 1 auto;
}
}
> .btn {
- height: $o-statusbar-height + 1;
+ height: $o-statusbar-height;
border: 1px solid transparent;
}
+ .btn {
+ @extend .text-nowrap;
+ padding-right: $btn-padding-x;
+ padding-left: $btn-padding-x;
+ }
}
@@ -60,3 +65,11 @@
}
}
}
+
+@include media-breakpoint-down(sm) {
+ .o_chatter .o_chatter_topbar > .o_topbar_right_area {
+ .o_chatter_button_attachment {
+ margin-right: initial;
+ }
+ }
+}
diff --git a/addons/mail/static/src/scss/composer.scss b/addons/mail/static/src/scss/composer.scss
index e7f7eb98d3b..75c62bbeae0 100644
--- a/addons/mail/static/src/scss/composer.scss
+++ b/addons/mail/static/src/scss/composer.scss
@@ -142,6 +142,9 @@
&:not(.o_chat_inline_composer) {
flex-flow: row wrap;
+ .o_composer_container {
+ max-width: 100%;
+ }
.o_composer_container, .o_composer_button_send {
flex: 1 0 100%;
}
diff --git a/addons/mail/static/src/xml/thread.xml b/addons/mail/static/src/xml/thread.xml
index 9f490bba0b5..2a5fd7ee30b 100644
--- a/addons/mail/static/src/xml/thread.xml
+++ b/addons/mail/static/src/xml/thread.xml
@@ -38,9 +38,9 @@
<t t-set="model" t-value="widget.modelName"/>
<div class="o_viewer-header">
<span class="o_image_caption">
- <i class="fa fa-picture-o mr8" t-if="widget.activeAttachment.type == 'image'" role="img" aria-label="Image" title="Image"/>
- <i class="fa fa-file-text mr8" t-if="widget.activeAttachment.type == 'application/pdf'" role="img" aria-label="PDF file" title="PDF file"/>
- <i class="fa fa-video-camera mr8" t-if="widget.activeAttachment.type == 'video'" role="img" aria-label="Video" title="Video"/>
+ <i class="fa fa-picture-o mr8" t-if="widget.activeAttachment.fileType == 'image'" role="img" aria-label="Image" title="Image"/>
+ <i class="fa fa-file-text mr8" t-if="widget.activeAttachment.fileType == 'application/pdf'" role="img" aria-label="PDF file" title="PDF file"/>
+ <i class="fa fa-video-camera mr8" t-if="widget.activeAttachment.fileType == 'video'" role="img" aria-label="Video" title="Video"/>
<t t-esc="widget.activeAttachment.name"/>
<a role="button" href="#" class="o_download_btn ml8 small" data-toggle="tooltip" data-placement="right" title="Download"><i class="fa fa-fw fa-download" role="img" aria-label="Download"/></a>
</span>
@@ -48,19 +48,19 @@
</div>
<div class="o_viewer_img_wrapper">
<div class="o_viewer_zoomer">
- <div t-if="widget.activeAttachment.type == 'image'" class="o_loading_img text-center">
+ <div t-if="widget.activeAttachment.fileType == 'image'" class="o_loading_img text-center">
<i class="fa fa-circle-o-notch fa-spin text-gray-light fa-3x fa-fw" role="img" aria-label="Loading" title="Loading"/>
</div>
- <img t-if="widget.activeAttachment.type === 'image'" class="o_viewer_img" t-attf-src="/web/image/#{widget.activeAttachment.id}?unique=1&amp;signature=#{widget.activeAttachment.checksum}&amp;model=#{model}" alt="Viewer"/>
- <iframe t-if="widget.activeAttachment.type == 'application/pdf'" class="mt32 o_viewer_pdf" t-attf-src="/web/static/lib/pdfjs/web/viewer.html?file=/web/content/#{widget.activeAttachment.id}?model%3D#{model}" />
- <iframe t-if="(widget.activeAttachment.type || '').indexOf('text') !== -1" class="mt32 o_viewer_text" t-attf-src="/web/content/#{widget.activeAttachment.id}?model%3D#{model}" />
- <iframe t-if="widget.activeAttachment.type == 'youtu'" class="mt32 o_viewer_text" allow="autoplay; encrypted-media" width="560" height="315" t-attf-src="https://www.youtube.com/embed/#{widget.activeAttachment.youtube}"/>
- <video t-if="widget.activeAttachment.type == 'video'" class="o_viewer_video" controls="controls">
+ <img t-if="widget.activeAttachment.fileType === 'image'" class="o_viewer_img" t-attf-src="/web/image/#{widget.activeAttachment.id}?unique=1&amp;signature=#{widget.activeAttachment.checksum}&amp;model=#{model}" alt="Viewer"/>
+ <iframe t-if="widget.activeAttachment.fileType == 'application/pdf'" class="mt32 o_viewer_pdf" t-attf-src="/web/static/lib/pdfjs/web/viewer.html?file=/web/content/#{widget.activeAttachment.id}?model%3D#{model}" />
+ <iframe t-if="(widget.activeAttachment.fileType || '').indexOf('text') !== -1" class="mt32 o_viewer_text" t-attf-src="/web/content/#{widget.activeAttachment.id}?model%3D#{model}" />
+ <iframe t-if="widget.activeAttachment.fileType == 'youtu'" class="mt32 o_viewer_text" allow="autoplay; encrypted-media" width="560" height="315" t-attf-src="https://www.youtube.com/embed/#{widget.activeAttachment.youtube}"/>
+ <video t-if="widget.activeAttachment.fileType == 'video'" class="o_viewer_video" controls="controls">
<source t-attf-src="/web/image/#{widget.activeAttachment.id}?model=#{model}" t-att-data-type="widget.activeAttachment.mimetype"/>
</video>
</div>
</div>
- <div t-if="widget.activeAttachment.type == 'image'" class="o_viewer_toolbar btn-toolbar" role="toolbar">
+ <div t-if="widget.activeAttachment.fileType == 'image'" class="o_viewer_toolbar btn-toolbar" role="toolbar">
<div class="btn-group ml0" role="group">
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_zoom_in" data-toggle="tooltip" title="Zoom In"><i class="fa fa-fw fa-plus" role="img" aria-label="Zoom In"/></a>
<a role="button" href="#" class="o_viewer_toolbar_btn btn o_zoom_reset disabled" data-toggle="tooltip" title="Reset Zoom"><i class="fa fa-fw fa-search" role="img" aria-label="Reset Zoom"/></a>
diff --git a/addons/mail/static/tests/document_viewer_tests.js b/addons/mail/static/tests/document_viewer_tests.js
index 5d3dcf7069f..b5748ab72ee 100644
--- a/addons/mail/static/tests/document_viewer_tests.js
+++ b/addons/mail/static/tests/document_viewer_tests.js
@@ -207,5 +207,24 @@ QUnit.module('DocumentViewer', {
assert.ok(viewer.isDestroyed(), 'viewer should be destroyed');
});
+
+ QUnit.test('fileType and integrity test', async function (assert) {
+ assert.expect(3);
+
+ var viewer = await createViewer({
+ attachmentID: 2,
+ attachments: this.attachments,
+ });
+
+ assert.strictEqual(this.attachments[1].type, 'url',
+ "the type should be url");
+ assert.strictEqual(this.attachments[1].fileType, 'youtu',
+ "there should be a fileType 'youtu'");
+ assert.strictEqual(this.attachments[1].youtube, 'FYqW0Gdwbzk',
+ "there should be a youtube token");
+
+ viewer.destroy();
+ });
+
});
});