diff options
| author | jpr-odoo <jpr@openerp.com> | 2017-09-04 18:18:12 +0200 |
|---|---|---|
| committer | Yannick Tivisse <yti@odoo.com> | 2017-09-05 15:52:15 +0200 |
| commit | 46699c5214229ea8aebcc04e08d0786fd2b67f35 (patch) | |
| tree | 60f74e793b442ba8d2379f68743fb5a4724472e0 | |
| parent | fa432175e991be13035757e5174625f954bae171 (diff) | |
[IMP] mail: Add a preview popup for attachments
Purpose
=======
The goal is that when you click on an attachment, you should get a preview of it and then you get the possibility to download it.
| -rw-r--r-- | addons/im_livechat/views/im_livechat_channel_templates.xml | 1 | ||||
| -rw-r--r-- | addons/mail/controllers/main.py | 1 | ||||
| -rw-r--r-- | addons/mail/static/src/js/composer.js | 26 | ||||
| -rw-r--r-- | addons/mail/static/src/js/document_viewer.js | 302 | ||||
| -rw-r--r-- | addons/mail/static/src/js/thread.js | 28 | ||||
| -rw-r--r-- | addons/mail/static/src/less/composer.less | 129 | ||||
| -rw-r--r-- | addons/mail/static/src/less/thread.less | 1 | ||||
| -rw-r--r-- | addons/mail/static/src/xml/thread.xml | 124 | ||||
| -rw-r--r-- | addons/mail/static/tests/chatter_tests.js | 86 | ||||
| -rw-r--r-- | addons/mail/views/mail_templates.xml | 1 | ||||
| -rw-r--r-- | addons/web/static/src/less/mimetypes.less | 2 | ||||
| -rw-r--r-- | addons/website_livechat/views/website_livechat.xml | 1 |
12 files changed, 677 insertions, 25 deletions
diff --git a/addons/im_livechat/views/im_livechat_channel_templates.xml b/addons/im_livechat/views/im_livechat_channel_templates.xml index ff9b5ab1e25..e40a311c892 100644 --- a/addons/im_livechat/views/im_livechat_channel_templates.xml +++ b/addons/im_livechat/views/im_livechat_channel_templates.xml @@ -135,6 +135,7 @@ <script type="text/javascript" src="/bus/static/src/js/bus.js"></script> <script type="text/javascript" src="/mail/static/src/js/chat_window.js"></script> <script type="text/javascript" src="/mail/static/src/js/thread.js"></script> + <script type="text/javascript" src="/mail/static/src/js/document_viewer.js"></script> <script type="text/javascript" src="/im_livechat/static/src/js/im_livechat.js"></script> <t t-call="web.less_helpers"/> <link rel="stylesheet" href="/im_livechat/static/src/less/im_livechat_bootstrap.less"/> diff --git a/addons/mail/controllers/main.py b/addons/mail/controllers/main.py index c1b4433e74a..6146b5b37e5 100644 --- a/addons/mail/controllers/main.py +++ b/addons/mail/controllers/main.py @@ -2,7 +2,6 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. import base64 -import json import logging import psycopg2 import werkzeug diff --git a/addons/mail/static/src/js/composer.js b/addons/mail/static/src/js/composer.js index 29806a08e51..f4ba98696a5 100644 --- a/addons/mail/static/src/js/composer.js +++ b/addons/mail/static/src/js/composer.js @@ -2,6 +2,7 @@ odoo.define('mail.composer', function (require) { "use strict"; var chat_mixin = require('mail.chat_mixin'); +var DocumentViewer = require('mail.DocumentViewer'); var utils = require('mail.utils'); var core = require('web.core'); @@ -354,6 +355,8 @@ var BasicComposer = Widget.extend(chat_mixin, { "click .o_composer_button_send": "send_message", "click .o_composer_button_add_attachment": "on_click_add_attachment", "click .o_attachment_delete": "on_attachment_delete", + "click .o_attachment_download": "_onAttachmentDownload", + "click .o_attachment_view": "_onAttachmentView", }, // RPCs done to fetch the mention suggestions are throttled with the following value MENTION_THROTTLE: 200, @@ -758,6 +761,29 @@ var BasicComposer = Widget.extend(chat_mixin, { focus: function () { this.$input.focus(); }, + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {MouseEvent} event + */ + _onAttachmentDownload: function (event) { + event.stopPropagation(); + }, + /** + * @private + * @param {MouseEvent} event + */ + _onAttachmentView: function (event) { + var activeAttachmentID = $(event.currentTarget).data('id'); + var attachments = this.get('attachment_ids'); + if (activeAttachmentID) { + var attachmentViewer = new DocumentViewer(this, attachments, activeAttachmentID); + attachmentViewer.appendTo($('body')); + } + }, }); var ExtendedComposer = BasicComposer.extend({ diff --git a/addons/mail/static/src/js/document_viewer.js b/addons/mail/static/src/js/document_viewer.js new file mode 100644 index 00000000000..679e483c899 --- /dev/null +++ b/addons/mail/static/src/js/document_viewer.js @@ -0,0 +1,302 @@ +odoo.define('mail.DocumentViewer', function (require) { +"use strict"; + +var core = require('web.core'); +var Widget = require('web.Widget'); + +var QWeb = core.qweb; + +var SCROLL_ZOOM_STEP = 0.1; +var ZOOM_STEP = 0.5; + +var DocumentViewer = Widget.extend({ + template: "DocumentViewer", + events: { + 'click .o_download_btn': '_onDownload', + 'click .o_viewer_img': '_onImageClicked', + 'click .o_viewer_video': '_onVideoClicked', + 'click .move_next': '_onNext', + 'click .move_previous': '_onPrevious', + 'click .o_zoom_in': '_onZoomIn', + 'click .o_zoom_out': '_onZoomOut', + 'click .o_close_btn, .o_viewer_img_wrapper': '_onClose', + 'click .o_print_btn': '_onPrint', + 'DOMMouseScroll .o_viewer_content': '_onScroll', // Firefox + 'mousewheel .o_viewer_content': '_onScroll', // Chrome, Safari, IE + 'keydown': '_onKeydown', + 'mousedown .o_viewer_img': '_onStartDrag', + 'mousemove .o_viewer_content': '_onDrag', + 'mouseup .o_viewer_content': '_onEndDrag' + }, + /** + * The documentViewer takes an array of objects describing attachments in + * argument, and the ID of an active attachment (the one to display first). + * Documents that are not of type image or video are filtered out. + * + * @override + * @param {Array[Object]} attachments list of attachments + * @param {integer} activeAttachmentID + */ + init: function (parent, attachments, activeAttachmentID) { + this._super.apply(this, arguments); + this.attachment = _.filter(attachments, function (attachment) { + var type = attachment.mimetype.split('/').shift(); + if (type === 'image' || type === 'video') { + attachment.type = type; + return true; + } + }); + this.activeAttachment = _.findWhere(attachments, {id: activeAttachmentID}); + this._reset(); + }, + /** + * Open a modal displaying the active attachment + * @override + */ + start: function () { + this.$el.modal('show'); + this.$el.on('hidden.bs.modal', _.bind(this._onDestroy, this)); + this.$('.o_viewer_img').load(_.bind(this._onImageLoaded, this)); + return this._super.apply(this, arguments); + }, + + //-------------------------------------------------------------------------- + // Private + //--------------------------------------------------------------------------- + + /** + * @private + */ + _next: function () { + var index = _.findIndex(this.attachment, this.activeAttachment); + index = (index + 1) % this.attachment.length; + this.activeAttachment = this.attachment[index]; + this._updateContent(); + }, + /** + * @private + */ + _previous: function () { + var index = _.findIndex(this.attachment, this.activeAttachment); + index = index === 0 ? this.attachment.length - 1 : index - 1; + this.activeAttachment = this.attachment[index]; + this._updateContent(); + }, + /** + * @private + */ + _reset: function () { + this.scale = 1; + this.dragStartX = this.dragstopX = 0; + this.dragStartY = this.dragstopY = 0; + }, + /** + * Render the active attachment + * + * @private + */ + _updateContent: function () { + this.$('.o_viewer_content').html(QWeb.render('DocumentViewer.Content', { + widget: this + })); + this.$('.o_viewer_img').load(_.bind(this._onImageLoaded, this)); + this._reset(); + }, + /** + * Zoom in/out image by provided scale + * + * @private + * @param {integer} scale + */ + _zoom: function (scale) { + if (scale > 0.5) { + this.$('.o_viewer_img').css('transform', 'scale3d(' + scale + ', ' + scale + ', 1)'); + this.scale = scale; + } + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {MouseEvent} e + */ + _onClose: function (e) { + e.preventDefault(); + this.$el.modal('hide'); + }, + /** + * When popup close complete destroyed modal even DOM footprint too + * @private + */ + _onDestroy: function () { + if (this.isDestroyed()) { + return; + } + this.$el.modal('hide'); + this.$el.remove(); + }, + /** + * @private + * @param {MouseEvent} e + */ + _onDownload: function (e) { + e.preventDefault(); + window.location = '/web/content/' + this.activeAttachment.id + '?download=true'; + }, + /** + * @private + * @param {MouseEvent} e + */ + _onDrag: function (e) { + e.preventDefault(); + if (this.enableDrag) { + var $image = this.$('.o_viewer_img'); + var $zoomer = this.$('.o_viewer_zoomer'); + var top = $image.prop('offsetHeight') * this.scale > $zoomer.height() ? e.clientY - this.dragStartY : 0; + var left = $image.prop('offsetWidth') * this.scale > $zoomer.width() ? e.clientX - this.dragStartX : 0; + $zoomer.css("transform", "translate3d("+ left +"px, " + top + "px, 0)"); + } + }, + /** + * @private + * @param {MouseEvent} e + */ + _onEndDrag: function (e) { + e.preventDefault(); + if (this.enableDrag) { + this.enableDrag = false; + this.dragstopX = e.clientX - this.dragStartX; + this.dragstopY = e.clientY - this.dragStartY; + } + }, + /** + * On click of image do not close modal so stop event propagation + * + * @private + * @param {MouseEvent} e + */ + _onImageClicked: function (e) { + e.stopPropagation(); + }, + /** + * Remove loading indicator when image loaded + * @private + */ + _onImageLoaded: function () { + this.$('.o_loading_img').hide(); + }, + /** + * Move next previous attachment on keyboard right left key + * + * @private + * @param {KeyEvent} e + */ + _onKeydown: function (e){ + switch (e.which) { + case $.ui.keyCode.RIGHT: + e.preventDefault(); + this._next(); + break; + case $.ui.keyCode.LEFT: + e.preventDefault(); + this._previous(); + break; + } + }, + /** + * @private + * @param {MouseEvent} e + */ + _onNext: function (e) { + e.preventDefault(); + this._next(); + }, + /** + * @private + * @param {MouseEvent} e + */ + _onPrevious: function (e) { + e.preventDefault(); + this._previous(); + }, + /** + * @private + * @param {MouseEvent} e + */ + _onPrint: function (e) { + e.preventDefault(); + var src = this.$('.o_viewer_img').prop('src'); + var script = QWeb.render('PrintImage', { + src: src + }); + var printWindow = window.open('about:blank', "_new"); + printWindow.document.open(); + printWindow.document.write(script); + printWindow.document.close(); + }, + /** + * Zoom image on scroll + * + * @private + * @param {MouseEvent} e + */ + _onScroll: function (e) { + var scale; + if (e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0) { + scale = this.scale + SCROLL_ZOOM_STEP; + this._zoom(scale); + } else { + scale = this.scale - SCROLL_ZOOM_STEP; + this._zoom(scale); + } + }, + /** + * @private + * @param {MouseEvent} e + */ + _onStartDrag: function (e) { + e.preventDefault(); + this.enableDrag = true; + this.dragStartX = e.clientX - (this.dragstopX || 0); + this.dragStartY = e.clientY - (this.dragstopY || 0); + }, + /** + * On click of video do not close modal so stop event propagation + * and provide play/pause the video instead of quitting it + * + * @private + * @param {MouseEvent} e + */ + _onVideoClicked: function (e) { + e.stopPropagation(); + var videoElement = e.target; + if (videoElement.paused) { + videoElement.play(); + } else { + videoElement.pause(); + } + }, + /** + * @private + * @param {MouseEvent} e + */ + _onZoomIn: function (e) { + e.preventDefault(); + var scale = this.scale + ZOOM_STEP; + this._zoom(scale); + }, + /** + * @private + * @param {MouseEvent} e + */ + _onZoomOut: function (e) { + e.preventDefault(); + var scale = this.scale - ZOOM_STEP; + this._zoom(scale); + }, +}); +return DocumentViewer; +}); diff --git a/addons/mail/static/src/js/thread.js b/addons/mail/static/src/js/thread.js index 038bbf93de9..80d4c4c8a4c 100644 --- a/addons/mail/static/src/js/thread.js +++ b/addons/mail/static/src/js/thread.js @@ -2,6 +2,7 @@ odoo.define('mail.ChatThread', function (require) { "use strict"; var core = require('web.core'); +var DocumentViewer = require('mail.DocumentViewer'); var Widget = require('web.Widget'); var QWeb = core.qweb; @@ -30,6 +31,8 @@ var Thread = Widget.extend({ "click img": "on_click_redirect", "click strong": "on_click_redirect", "click .o_thread_show_more": "on_click_show_more", + "click .o_attachment_download": "_onAttachmentDownload", + "click .o_attachment_view": "_onAttachmentView", "click .o_thread_message_needaction": function (event) { var message_id = $(event.currentTarget).data('message-id'); this.trigger("mark_as_read", message_id); @@ -110,6 +113,8 @@ var Thread = Widget.extend({ ORDER: ORDER, })); + this.attachments = _.uniq(_.flatten(_.map(messages, 'attachment_ids'))); + _.each(msgs, function(msg) { var $msg = self.$('.o_thread_message[data-message-id="'+ msg.id +'"]'); $msg.find('.o_mail_timestamp').data('date', msg.date); @@ -300,6 +305,29 @@ var Thread = Widget.extend({ destroy: function () { clearInterval(this.update_timestamps_interval); }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + * @param {MouseEvent} event + */ + _onAttachmentDownload: function (event) { + event.stopPropagation(); + }, + /** + * @private + * @param {MouseEvent} event + */ + _onAttachmentView: function (event) { + var activeAttachmentID = $(event.currentTarget).data('id'); + if (activeAttachmentID) { + var attachmentViewer = new DocumentViewer(this, this.attachments, activeAttachmentID); + attachmentViewer.appendTo($('body')); + } + }, }); Thread.ORDER = ORDER; diff --git a/addons/mail/static/src/less/composer.less b/addons/mail/static/src/less/composer.less index 970d0649aa9..4073cef80c2 100644 --- a/addons/mail/static/src/less/composer.less +++ b/addons/mail/static/src/less/composer.less @@ -238,36 +238,60 @@ 100% { background: @odoo-brand-optional } } -@o-mail-attachment-image-size: 60px; +@o-mail-attachment-image-size: 100px; .o_attachment { position: relative; - width: 2*@o-mail-attachment-image-size; + vertical-align: top; display: inline-block; - height: @o-mail-attachment-image-size; text-align: center; - margin-bottom: 15px; - - .o_image { - .o-position-absolute(@top: 0, @left: @o-mail-attachment-image-size/2); - width: @o-mail-attachment-image-size; - height: @o-mail-attachment-image-size; + width: @o-mail-attachment-image-size; + margin: 5px; + .o_image_box { + position: relative; + img { + width: @o-mail-attachment-image-size; + height: @o-mail-attachment-image-size; + } + .o_image_overlay{ + display: none; + } + &:hover .o_image_overlay { + display: block; + .o-position-absolute(@top: 0, @left: 0, @right:0, @bottom:0); + z-index: 20; + background: rgba(0, 0, 0, 0.5); + overflow: hidden; + cursor: pointer; + .o_attachment_download { + .o-position-absolute(@left: 10px, @bottom:5px); + } + .o_attachment_play { + .o-position-absolute(@top: 50%, @left: 50%); + transform: translate(-50%, -50%); + } + .o_overlay_download { + width: 100%; + height: 100%; + } + i { + color: #FFFFFF; + } + } } - - .o_attachment_name { - display: inline-block; - max-width: 100%; - margin-top: @o-mail-attachment-image-size; - overflow: hidden; + .caption { text-overflow: ellipsis; white-space: nowrap; - color: @odoo-main-text-color; + overflow: hidden; + padding: 5px; + a { + color: @odoo-main-text-color; + } } - .o_attachment_progress_bar { display: none; } .o_attachment_delete { - .o-position-absolute(@top: 0, @right: 0); + .o-position-absolute(@top: -10px, @right: -8px); color: @odoo-main-text-color; cursor: pointer; opacity: 0; @@ -289,9 +313,76 @@ display: none; } } - &:hover .o_attachment_delete { opacity: 1; .o-transition(opacity, 0.2s, linear); } } + +.o_modal_fullscreen { + .o_viewer_content { + width: 100%; + height: 100%; + position: relative; + cursor: pointer; + .o_viewer-header { + width: 100%; + height: 45px; + padding: 10px 10px 0; + background-color: rgba(0, 0, 0, 0.45); + cursor: auto; + .o_image_caption { + color: #FFFFFF; + display: inline; + } + } + .o_loading_img { + .o-position-absolute(@top: 50%); + width: 25px; + right: 50%; + z-index: 1; + } + .o_viewer_img_wrapper { + width: 100%; + height: 100%; + position: fixed; + .o_viewer_zoomer { + width: 100%; + height: 100%; + .o-flex-display(); + justify-content: center; + align-items: center; + img, video { + max-width: 100%; + max-height: 100%; + transition: 0.3s cubic-bezier(0, 0, 0.49, 1.6) 0s, opacity 0.15s; + } + .o_viewer_video { + height: 80%; + } + } + } + .o_viewer_toolbar { + .o-position-absolute(@left: 50%); + bottom: 15px; + transform: translate(-50%, -50%); + padding: 8px 10px 0px 10px; + background-color: rgba(0, 0, 0, 0.6); + border-radius: 4px; + } + } + .arrow { + .o-position-absolute(@top: 50%); + color: #FFFFFF; + } + .arrow-left { + left: 0; + } + + .arrow-right { + right: 0; + } + i.fa { + color: #FFFFFF; + } +} diff --git a/addons/mail/static/src/less/thread.less b/addons/mail/static/src/less/thread.less index be39413f573..41512f60b08 100644 --- a/addons/mail/static/src/less/thread.less +++ b/addons/mail/static/src/less/thread.less @@ -127,7 +127,6 @@ } img { max-width: 100%; - height: auto; } .o_mail_body_long { diff --git a/addons/mail/static/src/xml/thread.xml b/addons/mail/static/src/xml/thread.xml index 6f23e4a5e34..43cf896e1cc 100644 --- a/addons/mail/static/src/xml/thread.xml +++ b/addons/mail/static/src/xml/thread.xml @@ -18,6 +18,87 @@ </div> </t> + + <t t-name="DocumentViewer.Content"> + <div class="o_viewer_content"> + <div class="o_viewer-header"> + <h2 class="o_image_caption"><t t-esc="widget.activeAttachment.name"/></h2> + <ul class="list-inline pull-right"> + <li t-if="widget.activeAttachment.type == 'image'"> + <a class="o_print_btn" href="#"> + <i class="fa fa-2x fa-print"/> + </a> + </li> + <li> + <a class="o_close_btn" href="#"> + <i class="fa fa-2x fa-times"/> + </a> + </li> + </ul> + </div> + <div class="o_viewer_img_wrapper"> + <div class="o_viewer_zoomer"> + <div t-if="widget.activeAttachment.type == 'image'" class="o_loading_img"> + <i class="fa fa-spinner fa-spin fa-3x fa-fw" aria-hidden="true"/> + </div> + <img t-if="widget.activeAttachment.type == 'image'" class="o_viewer_img" t-attf-src="/web/image/#{widget.activeAttachment.id}?unique=1"/> + <video t-if="widget.activeAttachment.type == 'video'" class="o_viewer_video" controls="controls"> + <source t-attf-src="/web/image/#{widget.activeAttachment.id}" t-att-data-type="widget.activeAttachment.mimetype"/> + </video> + </div> + </div> + <div t-if="widget.activeAttachment.type == 'image'" class="o_viewer_toolbar"> + <ul class="list-inline"> + <li> + <a class="o_zoom_out" href="#"> + <i class="fa fa-2x fa-search-minus"></i> + </a> + </li> + <li> + <a class="o_zoom_in" href="#"> + <i class="fa fa-2x fa-search-plus"></i> + </a> + </li> + <li> + <a class="o_download_btn" href="#"> + <i class="fa fa-2x fa-download"/> + </a> + </li> + </ul> + </div> + </div> + </t> + + <t t-name="DocumentViewer"> + <div class="modal o_modal_fullscreen" tabindex="-1" role="dialog" aria-hidden="true"> + <t t-call="DocumentViewer.Content"/> + <a class="arrow arrow-left move_previous" href="#"> + <span class="fa fa-3x fa-chevron-left"/> + </a> + <a class="arrow arrow-right move_next" href="#"> + <span class="fa fa-3x fa-chevron-right"/> + </a> + </div> + </t> + <t t-name="PrintImage"> + <html> + <head> + <script> + function onload_img() { + setTimeout('print_img()', 10); + } + function print_img() { + window.print(); + window.close(); + } + </script> + </head> + <body onload='onload_img()'> + <img t-att-src='src' /> + </body> + </html> + </t> + <!-- When a channel is empty--> <div t-name="mail.EmptyChannel" class="o_mail_no_content"> <t t-if="options.channel_id==='channel_inbox'"> @@ -175,10 +256,47 @@ </t> <t t-name="mail.Attachment"> + <t t-set="type" t-value="attachment.mimetype.split('/').shift()"/> <div t-attf-class="o_attachment #{attachment.upload ? 'o_attachment_uploading' : ''}" t-att-title="attachment.name"> - <a class="o_image" t-att-href='attachment.url' target="_blank" t-att-data-mimetype="attachment.mimetype" t-attf-data-src="/web/image/#{attachment.id}/100x80"> - <span class='o_attachment_name'><t t-esc='attachment.name'/></span> - </a> + <t t-if="type == 'image'"> + <div class="o_image_box"> + <img t-attf-src="/web/image/#{attachment.id}/200x200/?crop=True"/> + <div t-attf-class="o_image_overlay o_attachment_view" t-att-data-id="attachment.id"> + <a class="o_attachment_download" t-att-href='attachment.url' target="_blank"> + <i t-attf-class="fa fa-2x fa-arrow-circle-o-down" title="Download this attachment" aria-hidden="true"></i> + </a> + </div> + </div> + </t> + <t t-elif="type == 'video'"> + <div class="o_image_box o_image_preview"> + <img class="o_image" t-att-data-mimetype="attachment.mimetype"/> + <div t-attf-class="o_image_overlay o_attachment_view" t-att-data-id="attachment.id"> + <a class="o_attachment_play"> + <i t-attf-class="fa fa-2x fa-play-circle" title="Play this video" aria-hidden="true"></i> + </a> + <a class="o_attachment_download" t-att-href='attachment.url' target="_blank"> + <i t-attf-class="fa fa-2x fa-arrow-circle-o-down" title="Download this attachment" aria-hidden="true"></i> + </a> + </div> + </div> + </t> + <t t-else=""> + <div class="o_image_box"> + <img class="o_image" t-att-data-mimetype="attachment.mimetype"/> + <div t-attf-class="o_image_overlay"> + <a class="o_overlay_download" t-att-href='attachment.url' target="_blank"/> + <a class="o_attachment_download" t-att-href='attachment.url' target="_blank"> + <i t-attf-class="fa fa-2x fa-arrow-circle-o-down" title="Download this attachment" aria-hidden="true"></i> + </a> + </div> + </div> + </t> + <div class="caption"> + <a t-att-href='attachment.url' target="_blank"> + <t t-esc='attachment.name'/> + </a> + </div> <t t-if="editable"> <div class="o_attachment_delete"> <i class='fa fa-times-circle' title="Delete this attachment" t-att-data-id="attachment.id"/> diff --git a/addons/mail/static/tests/chatter_tests.js b/addons/mail/static/tests/chatter_tests.js index b5d7feab56e..337f3e9f9d1 100644 --- a/addons/mail/static/tests/chatter_tests.js +++ b/addons/mail/static/tests/chatter_tests.js @@ -494,6 +494,92 @@ QUnit.test('chatter: post, receive and star messages', function (assert) { }); }); +QUnit.test('chatter: Attachment viewer', function (assert) { + assert.expect(5); + this.data.partner.records[0].message_ids = [1]; + var messages = [{ + attachment_ids: [{ + filename: 'image1.jpg', + id:1, + mimetype: 'image/jpeg', + name: 'Test Image 1', + url: '/web/content/1?download=true' + },{ + filename: 'image2.jpg', + id:2, + mimetype: 'image/jpeg', + name: 'Test Image 2', + url: '/web/content/2?download=true' + },{ + filename: 'image3.jpg', + id:3, + mimetype: 'image/jpeg', + name: 'Test Image 3', + url: '/web/content/3?download=true' + }], + author_id: ["1", "John Doe"], + body: "Attachement viewer test", + date: moment("2016-12-20 09:35:40"), + displayed_author: "John Doe", + id: 1, + is_note: false, + is_starred: false, + model: 'partner', + res_id: 2, + }]; + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: '<form string="Partners">' + + '<sheet>' + + '<field name="foo"/>' + + '</sheet>' + + '<div class="oe_chatter">' + + '<field name="message_ids" widget="mail_thread" options="{\'display_log_button\': True}"/>' + + '</div>' + + '</form>', + res_id: 2, + mockRPC: function (route) { + if(_.str.contains(route, '/mail/attachment/preview/')){ + var canvas = document.createElement('canvas'); + return $.when(canvas.toDataURL()); + } + return this._super.apply(this, arguments); + }, + intercepts: { + get_messages: function (event) { + event.stopPropagation(); + var requested_msgs = _.filter(messages, function (msg) { + return _.contains(event.data.options.ids, msg.id); + }); + event.data.callback($.when(requested_msgs)); + }, + get_bus: function (event) { + event.stopPropagation(); + event.data.callback(new Bus()); + }, + }, + }); + assert.strictEqual(form.$('.o_thread_message .o_attachment').length, 3, + "there should be three attachment on message"); + assert.strictEqual(form.$('.o_thread_message .o_attachment .caption a').first().attr('href'), '/web/content/1?download=true', + "image caption should have correct download link"); + // click on first image attachement + form.$('.o_thread_message .o_attachment .o_image_box .o_image_overlay').first().click(); + assert.strictEqual($('.o_modal_fullscreen img.o_viewer_img[src*="/web/image/1?unique=1"]').length, 1, + "Modal popup should open with first image src"); + // click on next button + $('.modal .arrow.arrow-right.move_next span').click(); + assert.strictEqual($('.o_modal_fullscreen img.o_viewer_img[src*="/web/image/2?unique=1"]').length, 1, + "Modal popup should have now second image src"); + assert.strictEqual($('.o_modal_fullscreen .o_viewer_toolbar .o_download_btn').length, 1, + "Modal popup should have download button"); + // close attachment popup + $('.o_modal_fullscreen .o_viewer-header .o_close_btn').click(); + form.destroy(); +}); + QUnit.test('form activity widget: schedule next activity', function (assert) { assert.expect(5); this.data.partner.records[0].activity_ids = [1]; diff --git a/addons/mail/views/mail_templates.xml b/addons/mail/views/mail_templates.xml index 368978bb551..2fe052975c3 100644 --- a/addons/mail/views/mail_templates.xml +++ b/addons/mail/views/mail_templates.xml @@ -8,6 +8,7 @@ <script type="text/javascript" src="/mail/static/src/js/client_action.js"></script> <script type="text/javascript" src="/mail/static/src/js/chat_window.js"></script> <script type="text/javascript" src="/mail/static/src/js/extended_chat_window.js"></script> + <script type="text/javascript" src="/mail/static/src/js/document_viewer.js"></script> <script type="text/javascript" src="/mail/static/src/js/composer.js"></script> <script type="text/javascript" src="/mail/static/src/js/chat_manager.js"></script> <script type="text/javascript" src="/mail/static/src/js/chatter.js"></script> diff --git a/addons/web/static/src/less/mimetypes.less b/addons/web/static/src/less/mimetypes.less index 12e86a34ab8..ad0ddbacd81 100644 --- a/addons/web/static/src/less/mimetypes.less +++ b/addons/web/static/src/less/mimetypes.less @@ -2,7 +2,7 @@ background-image: url('/web/static/src/img/mimetypes/unknown.png'); background-size: contain; width: 100px; - height: 80px; + height: 100px; display: inline-block; background-position: center; background-repeat: no-repeat; diff --git a/addons/website_livechat/views/website_livechat.xml b/addons/website_livechat/views/website_livechat.xml index 6aef10b7211..523705d93a9 100644 --- a/addons/website_livechat/views/website_livechat.xml +++ b/addons/website_livechat/views/website_livechat.xml @@ -10,6 +10,7 @@ <xpath expr="." position="inside"> <script type="text/javascript" src="/bus/static/src/js/bus.js"></script> <script type="text/javascript" src="/mail/static/src/js/chat_window.js"></script> + <script type="text/javascript" src="/mail/static/src/js/document_viewer.js"></script> <script type="text/javascript" src="/mail/static/src/js/thread.js"></script> <script type="text/javascript" src="/im_livechat/static/src/js/im_livechat.js"></script> <link rel="stylesheet" href="/mail/static/src/less/chat_window.less"></link> |
