diff options
| author | Christophe Simonis <chs@odoo.com> | 2019-01-09 19:59:27 +0100 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2019-01-09 19:59:27 +0100 |
| commit | d7c5bc02cc2b27442f0d4c8aca70266762be2a32 (patch) | |
| tree | 3a675d15b539a4474be38704405b318bebecdce7 /addons/mail/static | |
| parent | 37b518f1749aff3d6ffb2246c32f2aa1e67d9067 (diff) | |
| parent | 8aa8548d8ab68feb13f3bde51c557db84877e809 (diff) | |
[MERGE] forward port branch saas-12.1 up to 8aa8548d8ab
Diffstat (limited to 'addons/mail/static')
19 files changed, 350 insertions, 90 deletions
diff --git a/addons/mail/static/src/js/attachment_box.js b/addons/mail/static/src/js/attachment_box.js index b42e8aeca95..f58c64f26e7 100644 --- a/addons/mail/static/src/js/attachment_box.js +++ b/addons/mail/static/src/js/attachment_box.js @@ -13,46 +13,43 @@ var AttachmentBox = Widget.extend({ events: { "click .o_attachment_download": "_onAttachmentDownload", "click .o_attachment_view": "_onAttachmentView", + "click .o_attachment_delete_cross": "_onDeleteAttachment", + "click .o_upload_attachments_button": "_onUploadAttachments", + "change .o_chatter_attachment_form .o_form_binary_form": "_onAddAttachment", }, /** * @override * @param {string} record.model * @param {Number} record.res_id + * @param {Object[]} attachments */ - init: function (parent, record) { + init: function (parent, record, attachments) { this._super.apply(this, arguments); + this.fileuploadId = _.uniqueId('oe_fileupload'); + $(window).on(this.fileuploadId, this._onUploaded.bind(this)); this.currentResID = record.res_id; this.currentResModel = record.model; - this.attachmentIDs = {}; + this.attachmentIDs = attachments; this.imageList = {}; this.otherList = {}; + + _.each(attachments, function (attachment) { + // required for compatibility with the chatter templates. + attachment.url = '/web/content/' + attachment.id + '?download=true'; + attachment.filename = attachment.datas_fname || 'unnamed'; + }); + var sortedAttachments = _.partition(attachments, function (att) { + return att.mimetype && att.mimetype.split('/')[0] === 'image'; + }); + this.imageList = sortedAttachments[0]; + this.otherList = sortedAttachments[1]; }, /** * @override */ - willStart: function () { - var self = this; - var domain = [ - ['res_id', '=', this.currentResID], - ['res_model', '=', this.currentResModel], - ]; - return $.when(this._super.apply(this, arguments), this._rpc({ - model: 'ir.attachment', - method: 'search_read', - domain: domain, - }).then(function (result) { - self.attachmentIDs = result; - _.each(result, function (attachment) { - attachment.url = '/web/content/' + attachment.id + '?download=true'; - // required for compatibility with the chatter templates. - attachment.filename = attachment.datas_fname || 'unnamed'; - }); - var sortedAttachments = _.partition(result, function (att) { - return att.mimetype && att.mimetype.split('/')[0] === 'image'; - }); - self.imageList = sortedAttachments[0]; - self.otherList = sortedAttachments[1]; - })); + destroy: function () { + $(window).off(this.fileuploadId); + this._super.apply(this, arguments); }, //-------------------------------------------------------------------------- @@ -60,8 +57,8 @@ var AttachmentBox = Widget.extend({ //-------------------------------------------------------------------------- /** - * @param {Object} record - */ + * @param {Object} record + */ update: function (record) { this.currentResID = record.res_id; this.currentResModel = record.model; @@ -72,6 +69,19 @@ var AttachmentBox = Widget.extend({ //-------------------------------------------------------------------------- /** + * Method triggered when user click on 'add attachment' and select a file + * + * @private + * @param {MouseEvent} ev + */ + _onAddAttachment: function (ev) { + var $input = $(ev.currentTarget).find('input.o_input_file'); + if ($input.val() !== '') { + var $binaryForm = this.$('form.o_form_binary_form'); + $binaryForm.submit(); + } + }, + /** * @private * @param {MouseEvent} ev * used to prevent the click from opening the document viewer. @@ -92,6 +102,33 @@ var AttachmentBox = Widget.extend({ attachmentViewer.appendTo($('body')); } }, + /** + * Opens File Explorer dialog if all fields are valid and record is saved + * + * @private + * @param {MouseEvent} ev + */ + _onUploadAttachments: function (ev) { + this.$('input.o_input_file').click(); + }, + /** + * @private + * @param {MouseEvent} ev + */ + _onDeleteAttachment: function (ev) { + ev.stopPropagation(); + var $target = $(ev.currentTarget); + this.trigger_up('delete_attachment', { + attachmentId: $target.data('id'), + attachmentName: $target.data('name') + }); + }, + /** + * @private + */ + _onUploaded: function() { + this.trigger_up('reload_attachment_box'); + }, }); return AttachmentBox; diff --git a/addons/mail/static/src/js/chatter.js b/addons/mail/static/src/js/chatter.js index 000353d1219..da23521f65f 100644 --- a/addons/mail/static/src/js/chatter.js +++ b/addons/mail/static/src/js/chatter.js @@ -4,6 +4,7 @@ odoo.define('mail.Chatter', function (require) { var Activity = require('mail.Activity'); var AttachmentBox = require('mail.AttachmentBox'); var ChatterComposer = require('mail.composer.Chatter'); +var Dialog = require('web.Dialog'); var Followers = require('mail.Followers'); var ThreadField = require('mail.ThreadField'); var mailUtils = require('mail.utils'); @@ -13,25 +14,28 @@ var config = require('web.config'); var core = require('web.core'); var Widget = require('web.Widget'); +var _t = core._t; var QWeb = core.qweb; // The purpose of this widget is to display the chatter area below the form view // -// It instanciates the optional mail_thread, mail_activity and mail_followers widgets. +// It instantiates the optional mail_thread, mail_activity and mail_followers widgets. // It Ensures that those widgets are appended at the right place, and allows them to communicate // with each other. -// It synchronizes the rendering of those widgets (as they may be asynchronous), to limitate +// It synchronizes the rendering of those widgets (as they may be asynchronous), to mitigate // the flickering when switching between records var Chatter = Widget.extend({ template: 'mail.Chatter', custom_events: { + delete_attachment: '_onDeleteAttachment', discard_record_changes: '_onDiscardRecordChanges', + reload_attachment_box: '_onReloadAttachmentBox', reload_mail_fields: '_onReloadMailFields', }, events: { 'click .o_chatter_button_new_message': '_onOpenComposerMessage', 'click .o_chatter_button_log_note': '_onOpenComposerNote', - 'click .o_chatter_button_attachment': '_onOpenAttachments', + 'click .o_chatter_button_attachment': '_onClickAttachmentButton', 'click .o_chatter_button_schedule_activity': '_onScheduleActivity', }, supportedFieldTypes: ['one2many'], @@ -52,15 +56,19 @@ var Chatter = Widget.extend({ this._super.apply(this, arguments); this._setState(record); - this._dp = new concurrency.DropPrevious(); + this.attachments = {}; + this.fields = {}; + this._areAttachmentsLoaded = false; + this._disableAttachmentBox = !!options.disable_attachment_box; + this._dp = new concurrency.DropPrevious(); + this._isAttachmentBoxOpen = false; // mention: get the prefetched partners and use them as mention suggestions // if there is a follower widget, the followers will be added to the // suggestions as well once fetched this._mentionPartnerSuggestions = this.call('mail_service', 'getMentionPartnerSuggestions'); this._mentionSuggestions = this._mentionPartnerSuggestions; - this.fields = {}; if (mailFields.mail_activity) { this.fields.activity = new Activity(this, mailFields.mail_activity, record, options); } @@ -74,16 +82,17 @@ var Chatter = Widget.extend({ this.hasLogButton = options.display_log_button || nodeOptions.display_log_button; this.postRefresh = nodeOptions.post_refresh || 'never'; } - this.attachmentBoxOpened = false; }, /** * @override */ start: function () { this._$topbar = this.$('.o_chatter_topbar'); - this.$('.o_topbar_right_area').append(QWeb.render('mail.chatter.Attachment.Button', { - count: this.record.data.message_attachment_count || 0, - })); + if(!this._disableAttachmentBox) { + this.$('.o_topbar_right_area').append(QWeb.render('mail.chatter.Attachment.Button', { + count: this.record.data.message_attachment_count || 0, + })); + } // render and append the buttons this._$topbar.prepend(QWeb.render('mail.chatter.Buttons', { newMessageButton: !!this.fields.thread, @@ -115,6 +124,8 @@ var Chatter = Widget.extend({ if (this.record.res_id !== record.res_id) { this._closeComposer(true); this._closeAttachments(); + this._areAttachmentsLoaded = false; + this.attachments = {}; } // update the state @@ -155,13 +166,12 @@ var Chatter = Widget.extend({ /** * @private - * @param {boolean} force */ _closeAttachments: function () { if (this.fields.attachments) { this.$('.o_chatter_button_attachment').removeClass('o_active_attach'); this.fields.attachments.destroy(); - this.attachmentBoxOpened = false; + this._isAttachmentBoxOpen = false; } }, /** @@ -231,22 +241,46 @@ var Chatter = Widget.extend({ _enableComposer: function () { this.$(".o_composer_button_send").prop('disabled', false); }, + /* + * @private + * @return {Deferred} + */ + _fetchAttachments: function () { + var self = this; + var domain = [ + ['res_id', '=', this.record.res_id], + ['res_model', '=', this.record.model], + ]; + return this._rpc({ + model: 'ir.attachment', + method: 'search_read', + domain: domain, + fields: ['id', 'name', 'datas_fname', 'mimetype'], + }).then(function (result) { + self._areAttachmentsLoaded = true; + self.attachments = result; + }); + + }, /** * @private */ - _openAttachments: function () { - var self = this; - this.fields.attachments = new AttachmentBox(this, this.record); - + _openAttachmentBox: function () { + if (this.fields.attachments) { + this._closeAttachments(); + } + this.fields.attachments = new AttachmentBox(this, this.record, this.attachments); var $anchor = this.$('.o_chatter_topbar'); if (this._composer) { - $anchor = this.$('.o_thread_composer'); + var $anchor = this.$('.o_thread_composer'); + } else { + var $anchor = this.$('.o_chatter_topbar'); } - this.fields.attachments.insertAfter($anchor).then(function () { - self.$el.addClass('o_chatter_composer_active'); - self.$('.o_chatter_button_attachment').addClass('o_active_attach'); - }); - this.attachmentBoxOpened = true; + this.fields.attachments.insertAfter($anchor); + this.$el.addClass('o_chatter_composer_active'); + this.$('.o_chatter_button_attachment').addClass('o_active_attach'); + + this._isAttachmentBoxOpen = true; }, /** * @private @@ -286,6 +320,7 @@ var Chatter = Widget.extend({ if (self._reloadAfterPost(messageData)) { self.trigger_up('reload'); } else if (messageData.attachment_ids.length) { + self._reloadAttachmentBox(); self.trigger_up('reload', {fieldNames: ['message_attachment_count']}); } }).fail(function () { @@ -322,6 +357,16 @@ var Chatter = Widget.extend({ }, /** * @private + */ + _reloadAttachmentBox: function () { + this._areAttachmentsLoaded = false; + if (this._isAttachmentBoxOpen) { + this._fetchAttachments().then(this._openAttachmentBox.bind(this)); + } + this.trigger_up('reload', { fieldNames: ['message_attachment_count'] }); + }, + /** + * @private * @param {Deferred} def * @returns {Deferred} */ @@ -344,7 +389,11 @@ var Chatter = Widget.extend({ self.fields.activity.$el.appendTo(self.$el); } if (self.fields.followers) { - self.fields.followers.$el.insertBefore(self.$('.o_chatter_button_attachment')); + if (self._disableAttachmentBox) { + self.fields.followers.$el.appendTo(self.$('.o_topbar_right_area')); + } else { + self.fields.followers.$el.insertBefore(self.$('.o_chatter_button_attachment')); + } } if (self.fields.thread) { self.fields.thread.$el.appendTo(self.$el); @@ -383,8 +432,7 @@ var Chatter = Widget.extend({ */ _updateAttachmentCounter: function () { var count = this.record.data.message_attachment_count || 0; - this.$('.o_chatter_attachment_button_count').html(' ('+ count +')'); - this.$('.o_chatter_button_attachment').toggleClass('o_hidden', !count); + this.$('.o_chatter_attachment_button_count').html(count); }, /** * @private @@ -427,12 +475,45 @@ var Chatter = Widget.extend({ /** * @private + * @param {OdooEvent} ev + * @param {integer} ev.data.attachmentId + * @param {String} ev.data.attachmentName + */ + _onDeleteAttachment: function (ev) { + ev.stopPropagation(); + var self = this; + var options = { + confirm_callback: function () { + self._rpc({ + model: 'ir.attachment', + method: 'unlink', + args: [parseInt(ev.data.attachmentId, 10)], + }) + .then(function () { + self._reloadAttachmentBox(); + self.fields.thread.removeAttachments([ev.data.attachmentId]); + self.trigger_up('reload'); + }); + } + }; + var promptText = _.str.sprintf(_t("Do you really want to delete %s?"), _.escape(ev.data.attachmentName)); + Dialog.confirm(this, promptText, options); + }, + /** + * @private */ - _onOpenAttachments: function () { - if (this.attachmentBoxOpened) { + _onClickAttachmentButton: function () { + if(this._disableAttachmentBox) { + return; + } + if (this._isAttachmentBoxOpen) { this._closeAttachments(); } else { - this._openAttachments(); + var def; + if (!this._areAttachmentsLoaded) { + def = this._fetchAttachments(); + } + $.when(def).then(this._openAttachmentBox.bind(this)); } }, /** @@ -485,6 +566,12 @@ var Chatter = Widget.extend({ }, /** * @private + */ + _onReloadAttachmentBox: function () { + this._reloadAttachmentBox(); + }, + /** + * @private * @param {OdooEvent} event * @param {string} event.name * @param {Object} event.data diff --git a/addons/mail/static/src/js/composers/chatter_composer.js b/addons/mail/static/src/js/composers/chatter_composer.js index cda91eab205..777467e6eb8 100644 --- a/addons/mail/static/src/js/composers/chatter_composer.js +++ b/addons/mail/static/src/js/composers/chatter_composer.js @@ -3,6 +3,7 @@ odoo.define('mail.composer.Chatter', function (require) { var BasicComposer = require('mail.composer.Basic'); var mailUtils = require('mail.utils'); +var session = require('web.session'); var core = require('web.core'); var viewDialogs = require('web.view_dialogs'); @@ -195,7 +196,7 @@ var ChatterComposer = BasicComposer.extend({ message = _.extend(message, { subtype: 'mail.mt_comment', message_type: 'comment', - context: self.context, + context: _.defaults({}, self.context, session.user_context), }); // Subtype diff --git a/addons/mail/static/src/js/discuss_mobile.js b/addons/mail/static/src/js/discuss_mobile.js index 30136fee798..549e05b78fd 100644 --- a/addons/mail/static/src/js/discuss_mobile.js +++ b/addons/mail/static/src/js/discuss_mobile.js @@ -16,7 +16,7 @@ if (!config.device.isMobile) { * Overrides Discuss module in mobile */ Discuss.include({ - template: 'mail.discuss_mobile', + contentTemplate: 'mail.discuss_mobile', events: _.extend(Discuss.prototype.events, { 'click .o_mail_mobile_tab': '_onMobileTabClicked', 'click .o_mailbox_inbox_item': '_onMobileInboxButtonClicked', diff --git a/addons/mail/static/src/js/models/messages/abstract_message.js b/addons/mail/static/src/js/models/messages/abstract_message.js index f5cf55f0ef1..c1ae22b9708 100644 --- a/addons/mail/static/src/js/models/messages/abstract_message.js +++ b/addons/mail/static/src/js/models/messages/abstract_message.js @@ -336,6 +336,14 @@ var AbstractMessage = Class.extend({ return false; }, /** + * @params {integer[]} attachmentIDs + */ + removeAttachments: function (attachmentIDs) { + this._attachmentIDs = _.reject(this._attachmentIDs, function (attachment) { + return _.contains(attachmentIDs, attachment.id); + }); + }, + /** * State whether this message should redirect to the author * when clicking on the author of this message. * diff --git a/addons/mail/static/src/js/models/threads/document_thread.js b/addons/mail/static/src/js/models/threads/document_thread.js index d902d69765c..6c15b39d25e 100644 --- a/addons/mail/static/src/js/models/threads/document_thread.js +++ b/addons/mail/static/src/js/models/threads/document_thread.js @@ -157,6 +157,14 @@ var DocumentThread = Thread.extend({ return true; }, /** + * @param {integer[]} attachmentIDs + */ + removeAttachmentsFromMessages: function (attachmentIDs) { + _.each(this.getMessages(), function (message) { + message.removeAttachments(attachmentIDs); + }); + }, + /** * Set list of message IDs of this document thread * * Useful in order to handle message history of the document thread, diff --git a/addons/mail/static/src/js/thread_field.js b/addons/mail/static/src/js/thread_field.js index 5c85a2adb37..a3807802ad7 100644 --- a/addons/mail/static/src/js/thread_field.js +++ b/addons/mail/static/src/js/thread_field.js @@ -71,6 +71,12 @@ var ThreadField = AbstractField.extend({ //-------------------------------------------------------------------------- /** + * @param {integer[]} attachmentIDs + */ + removeAttachments: function (attachmentIDs) { + this._documentThread.removeAttachmentsFromMessages(attachmentIDs); + }, + /** * @override * @return {boolean} */ diff --git a/addons/mail/static/src/js/thread_widget.js b/addons/mail/static/src/js/thread_widget.js index d812d403007..2e2b7e222c6 100644 --- a/addons/mail/static/src/js/thread_widget.js +++ b/addons/mail/static/src/js/thread_widget.js @@ -34,6 +34,7 @@ var ThreadWidget = Widget.extend({ 'click .o_thread_show_more': '_onClickShowMore', 'click .o_attachment_download': '_onAttachmentDownload', 'click .o_attachment_view': '_onAttachmentView', + 'click .o_attachment_delete_cross': '_onDeleteAttachment', 'click .o_thread_message_needaction': '_onClickMessageNeedaction', 'click .o_thread_message_star': '_onClickMessageStar', 'click .o_thread_message_reply': '_onClickMessageReply', @@ -411,6 +412,18 @@ var ThreadWidget = Widget.extend({ }); }, /** + * @private + * @param {MouseEvent} ev + */ + _onDeleteAttachment: function (ev) { + ev.stopPropagation(); + var $target = $(ev.currentTarget); + this.trigger_up('delete_attachment', { + attachmentId: $target.data('id'), + attachmentName: $target.data('name') + }); + }, + /** * @private * @param {Object} options * @param {integer} [options.channelID] diff --git a/addons/mail/static/src/js/tools/debug_manager.js b/addons/mail/static/src/js/tools/debug_manager.js index 4c768e8bb2d..452a062806f 100644 --- a/addons/mail/static/src/js/tools/debug_manager.js +++ b/addons/mail/static/src/js/tools/debug_manager.js @@ -23,6 +23,10 @@ DebugManager.include({ views: [[false, 'list'], [false, 'form']], type: 'ir.actions.act_window', domain: [['res_id', '=', selectedIDs[0]], ['model', '=', this._controller.modelName]], + context: { + default_res_model: this._controller.modelName, + default_res_id: selectedIDs[0], + }, }); }, }); diff --git a/addons/mail/static/src/js/tour.js b/addons/mail/static/src/js/tour.js index 6b7160f2aa6..c345f2cd8a4 100644 --- a/addons/mail/static/src/js/tour.js +++ b/addons/mail/static/src/js/tour.js @@ -7,33 +7,24 @@ var tour = require('web_tour.tour'); var _t = core._t; tour.register('mail_tour', { - url: "/web", -}, [tour.STEPS.SHOW_APPS_MENU_ITEM, { - trigger: '.o_app[data-menu-xmlid="mail.menu_root_discuss"]', - content: _t('Want to <b>get in touch</b> with your contacts? <i>Discuss with them here.</i>'), - position: 'right', - edition: 'community', -}, { - trigger: '.o_app[data-menu-xmlid="mail.menu_root_discuss"]', - content: _t('Want to <b>get in touch</b> with your contacts? <i>Discuss with them here.</i>'), - position: 'bottom', - edition: 'enterprise', -}, { - trigger: '.o_mail_discuss .o_mail_discuss_sidebar .o_add[data-type="public"]', + url: "/web#action=mail.discuss", +}, [{ + trigger: '.o_mail_discuss .o_mail_discuss_sidebar .o_add[data-type="multi_user_channel"]', content: _t("<p>Channels make it easy to organize information across different topics and groups.</p> <p>Try to <b>create your first channel</b> (e.g. sales, marketing, product XYZ, after work party, etc).</p>"), position: 'bottom', }, { - trigger: '.o_mail_discuss .o_mail_discuss_sidebar .o_mail_add_thread[data-type="public"]', + trigger: '.o_mail_discuss .o_mail_discuss_sidebar .o_mail_add_thread[data-type="multi_user_channel"]', content: _t("<p>Create a channel here.</p>"), position: 'right', + auto: true, run: function (actions) { var t = new Date().getTime(); actions.text("SomeChannel_" + t, this.$anchor.find("input")); }, }, { - trigger: ".ui-menu-item > a", - auto: true, - in_modal: false, + trigger: ".ui-autocomplete .ui-menu-item > a:contains(Private)", + content: _t("<p> Create a private channel.</p>"), + position: 'right', }, { trigger: '.o_mail_discuss .o_composer_text_field', content: _t("<p><b>Write a message</b> to the members of the channel here.</p> <p>You can notify someone with <i>'@'</i> or link another channel with <i>'#'</i>. Start your message with <i>'/'</i> to get the list of possible commands.</p>"), diff --git a/addons/mail/static/src/js/views/activity/activity_view.js b/addons/mail/static/src/js/views/activity/activity_view.js index b2c707f9d2d..9f0cec6b761 100644 --- a/addons/mail/static/src/js/views/activity/activity_view.js +++ b/addons/mail/static/src/js/views/activity/activity_view.js @@ -13,7 +13,7 @@ var _lt = core._lt; var ActivityView = AbstractView.extend({ accesskey: "a", display_name: _lt('Activity'), - icon: 'fa-th', + icon: 'fa-clock-o', config: _.extend({}, AbstractView.prototype.config, { Controller: ActivityController, Model: ActivityModel, diff --git a/addons/mail/static/src/scss/attachment_box.scss b/addons/mail/static/src/scss/attachment_box.scss index ab412bf52fe..a9aa6aec260 100644 --- a/addons/mail/static/src/scss/attachment_box.scss +++ b/addons/mail/static/src/scss/attachment_box.scss @@ -1,25 +1,36 @@ .oe_chatter { + .btn.o_active_attach { - color: #875A7B; height: 300px; } - .o_chatter_attachment { - padding: 3px; + .o_mail_chatter_attachments { + min-height: 50px; + + .o_chatter_attachment { + padding: 3px; + + input.o_input_file { + position: absolute; + top: 1px; + opacity: 0; + pointer-events: none; + } - .o_border_dashed { - position: relative; - margin-top: 15px; - margin-bottom: 30px; - border-bottom: 1px dashed gray('300'); - text-align: center; + .o_border_dashed { + position: relative; + margin-top: 5px; + margin-bottom: 5px; + border-bottom: 1px dashed gray('300'); + text-align: center; - .o_attach_title { + .o_attach_title { position: relative; top: 10px; margin: 0 auto; padding: 0 10px; font-weight: bold; background: white; + } } } } diff --git a/addons/mail/static/src/scss/chatter.scss b/addons/mail/static/src/scss/chatter.scss index 261552c2b23..599802382a1 100644 --- a/addons/mail/static/src/scss/chatter.scss +++ b/addons/mail/static/src/scss/chatter.scss @@ -4,6 +4,11 @@ width: 100%; padding-top: 0!important; + .o_attachment_delete_cross { + @include o-position-absolute($right: 6px, $top:7px); + cursor: pointer; + } + .o_spinner { text-align: center; font-size: large; @@ -21,9 +26,16 @@ position: relative; float: right; flex: 1 1 auto; + .o_chatter_button_attachment { - height: 2.3em; + height: $o-statusbar-height - 2px; float: right; + padding: 0px; + margin-right: 25px; + + .fa-paperclip, .o_chatter_attachment_button_count { + font-weight: bold; + } } .o_followers { height: $o-statusbar-height + 1; diff --git a/addons/mail/static/src/scss/composer.scss b/addons/mail/static/src/scss/composer.scss index aa5131b0de5..096c527aa16 100644 --- a/addons/mail/static/src/scss/composer.scss +++ b/addons/mail/static/src/scss/composer.scss @@ -434,6 +434,10 @@ $o-mail-attachment-margin: 5px; font-size: $font-size-sm; } + .o_attachment_delete_cross { + color: white; + } + .o_attachment_download { @include o-position-absolute($right: 7px, $bottom:7px); } diff --git a/addons/mail/static/src/xml/chatter.xml b/addons/mail/static/src/xml/chatter.xml index 7461f4b9055..7f8629f1bae 100644 --- a/addons/mail/static/src/xml/chatter.xml +++ b/addons/mail/static/src/xml/chatter.xml @@ -20,6 +20,16 @@ <t t-call="mail.Attachment"/> </t> </div> + <div class="o_chatter_attachment_form"> + <t t-call="HiddenInputFile"> + <t t-set="fileupload_id" t-value="widget.fileuploadId"/> + <t t-set="fileupload_action" t-translation="off">/web/binary/upload_attachment</t> + <t t-set="multi_upload" t-value="true"/> + <input type="hidden" name="model" t-att-value="widget.currentResModel"/> + <input type="hidden" name="id" t-att-value="widget.currentResID"/> + <center><span class="btn btn-link o_upload_attachments_button"><span class="fa fa-plus-square"/> Add Attachments</span></center> + </t> + </div> </div> </div> @@ -96,11 +106,11 @@ </t> <t t-name="mail.chatter.Attachment.Button"> - <button t-attf-class="btn btn-sm btn-link o_chatter_button_attachment #{!count and 'o_hidden' or ''}" title="View all the attachments of the current record"> + <button class="btn btn-link o_chatter_button_attachment" title="View all the attachments of the current record"> <span> <i class="fa fa-paperclip"/> <span class="o_chatter_attachment_button_count"> - <t t-esc="' ('+count+')'"/> + <t t-esc="count"/> </span> </span> </button> diff --git a/addons/mail/static/src/xml/composer.xml b/addons/mail/static/src/xml/composer.xml index ec95a6d5b61..ff4680d7851 100644 --- a/addons/mail/static/src/xml/composer.xml +++ b/addons/mail/static/src/xml/composer.xml @@ -51,9 +51,9 @@ <div t-name="mail.Composer.emojis" class="o_mail_emoji_container"> <t t-foreach="emojis" t-as="emoji"> - <button t-att-data-emoji="emoji.sources[0]" class="btn btn-link o_mail_emoji" t-att-title="emoji.description" t-att-aria-label="emoji.description"> + <span t-att-data-emoji="emoji.sources[0]" class="o_mail_emoji" t-att-title="emoji.description" t-att-aria-label="emoji.description"> <t t-raw="emoji.unicode"/> - </button> + </span> </t> </div> diff --git a/addons/mail/static/src/xml/thread.xml b/addons/mail/static/src/xml/thread.xml index 914168306b8..be73917a1b5 100644 --- a/addons/mail/static/src/xml/thread.xml +++ b/addons/mail/static/src/xml/thread.xml @@ -523,6 +523,7 @@ <div class="o_image_box"> <div class="o_attachment_image" t-attf-style="background-image:url('/web/image/#{attachment.id}/160x160/?crop=true')"/> <div t-attf-class="o_image_overlay o_attachment_view" t-att-data-id="attachment.id"> + <span class="fa fa-times o_attachment_delete_cross" t-att-title="'Delete ' + attachment.name" t-att-data-id="attachment.id" t-att-data-name="attachment.name"/> <span class="o_attachment_title text-white"><t t-esc="attachment.name"/></span> <a class="o_attachment_download" t-att-href='attachment.url'> <i t-attf-class="fa fa-download text-white" t-att-title="'Download ' + attachment.name" role="img" aria-label="Download"></i> @@ -546,6 +547,7 @@ <t t-set="type" t-value="attachment.mimetype and attachment.mimetype.split('/').shift()"/> <div t-attf-class="o_attachment #{ editable ? 'o_attachment_editable' : '' } #{attachment.upload ? 'o_attachment_uploading' : ''}" t-att-title="attachment.name"> <div class="o_attachment_wrap"> + <span t-if="!editable" class="fa fa-times o_attachment_delete_cross" t-att-title="'Delete ' + attachment.name" t-att-data-id="attachment.id" t-att-data-name="attachment.name"/> <t t-set="has_preview" t-value="type == 'image' or type == 'video' or attachment.mimetype == 'application/pdf'"/> <t t-set="ext" t-value="attachment.filename.split('.').pop()"/> diff --git a/addons/mail/static/tests/chatter_tests.js b/addons/mail/static/tests/chatter_tests.js index b6eec0cd5e4..ca6c6877b7c 100644 --- a/addons/mail/static/tests/chatter_tests.js +++ b/addons/mail/static/tests/chatter_tests.js @@ -292,7 +292,7 @@ QUnit.test('Activity Done keep feedback on blur', function (assert) { }); QUnit.test('attachmentBox basic rendering', function (assert) { - assert.expect(11); + assert.expect(19); this.data.partner.records.push({ id: 7, display_name: "attachment_test", @@ -334,6 +334,19 @@ QUnit.test('attachmentBox basic rendering', function (assert) { assert.containsOnce(form, '.o_attachment_image', "there should be an image preview"); assert.containsOnce(form, '.o_attachments_previews', "there should be a list of previews"); assert.containsOnce(form, '.o_attachments_list', "there should be a list of non previewable attachments"); + assert.containsOnce(form, '.o_upload_attachments_button', "there should be an 'Add Attachments' button"); + assert.containsOnce(form, '.o_form_binary_form', "there should be a binary form"); + + assert.containsOnce(form, 'input[name="model"]', "there should be an model input"); + var $modelInput = form.$('input[name="model"]'); + assert.hasAttrValue($modelInput, 'value', 'partner'); + assert.hasAttrValue($modelInput, 'type', 'hidden'); + + assert.containsOnce(form, 'input[name="model"]', "there should be an id input"); + var $resIdInput = form.$('input[name="id"]'); + assert.hasAttrValue($resIdInput, 'value', '7'); + assert.hasAttrValue($resIdInput, 'type', 'hidden'); + assert.strictEqual(form.$('.o_attachment_title').text(), 'name1', "the image name should be correct"); // since there are two elements "Download name2"; one "name" and the other "txt" as text content, the following test @@ -1466,6 +1479,55 @@ QUnit.test('chatter: Attachment viewer', function (assert) { form.destroy(); }); +QUnit.test('chatter: keep context when sending a message', function(assert) { + assert.expect(1); + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + services: this.services, + arch: '<form string="Partners">' + + '<sheet>' + + '<field name="foo"/>' + + '</sheet>' + + '<div class="oe_chatter">' + + '<field name="message_ids" widget="mail_thread"/>' + + '</div>' + + '</form>', + res_id: 2, + session: { + user_context: {lang: 'en_US'}, + }, + mockRPC: function (route, args) { + if (args.method === 'message_get_suggested_recipients') { + return $.when({2: []}); + } + if (args.method === 'message_post') { + assert.deepEqual(args.kwargs.context, { + default_model: "partner", + default_res_id: 2, + lang: "en_US", + mail_post_autofollow: true, + }, + "the context is incorrect"); + return $.when(57923); + } + if (args.method === 'message_format') { + return $.when([{ + author_id: [42, "Me"], + model: 'partner', + }]); + } + return this._super(route, args); + }, + }); + + testUtils.dom.click(form.$('.o_chatter_button_new_message')); + testUtils.fields.editInput(form.$('.oe_chatter .o_composer_text_field:first()'), 'Pouet'); + testUtils.dom.click(form.$('.oe_chatter .o_composer_button_send')); + form.destroy(); +}); + QUnit.test('form activity widget: read RPCs', function (assert) { // Records of model 'mail.activity' may be updated in business flows (e.g. // the date of a 'Meeting' activity is updated when the associated meeting diff --git a/addons/mail/static/tests/tools/debug_manager_tests.js b/addons/mail/static/tests/tools/debug_manager_tests.js index fa7aecd40d1..8b9312ca733 100644 --- a/addons/mail/static/tests/tools/debug_manager_tests.js +++ b/addons/mail/static/tests/tools/debug_manager_tests.js @@ -14,6 +14,10 @@ QUnit.module('Mail DebugManager', {}, function () { intercepts: { do_action: function (event) { assert.deepEqual(event.data.action, { + context: { + default_res_model: "testModel", + default_res_id: 5, + }, res_model: 'mail.message', name: "Manage Messages", views: [[false, 'list'], [false, 'form']], |
