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/src/js | |
| parent | 37b518f1749aff3d6ffb2246c32f2aa1e67d9067 (diff) | |
| parent | 8aa8548d8ab68feb13f3bde51c557db84877e809 (diff) | |
[MERGE] forward port branch saas-12.1 up to 8aa8548d8ab
Diffstat (limited to 'addons/mail/static/src/js')
| -rw-r--r-- | addons/mail/static/src/js/attachment_box.js | 91 | ||||
| -rw-r--r-- | addons/mail/static/src/js/chatter.js | 141 | ||||
| -rw-r--r-- | addons/mail/static/src/js/composers/chatter_composer.js | 3 | ||||
| -rw-r--r-- | addons/mail/static/src/js/discuss_mobile.js | 2 | ||||
| -rw-r--r-- | addons/mail/static/src/js/models/messages/abstract_message.js | 8 | ||||
| -rw-r--r-- | addons/mail/static/src/js/models/threads/document_thread.js | 8 | ||||
| -rw-r--r-- | addons/mail/static/src/js/thread_field.js | 6 | ||||
| -rw-r--r-- | addons/mail/static/src/js/thread_widget.js | 13 | ||||
| -rw-r--r-- | addons/mail/static/src/js/tools/debug_manager.js | 4 | ||||
| -rw-r--r-- | addons/mail/static/src/js/tour.js | 25 | ||||
| -rw-r--r-- | addons/mail/static/src/js/views/activity/activity_view.js | 2 |
11 files changed, 229 insertions, 74 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, |
