From bb197b1f870c64c120462f044441c19ceaf2e97b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Wed, 4 Sep 2019 09:19:49 +0000 Subject: [PATCH] [MOV] portal: split portal chatter from composer PURPOSE Allow to manage attachments when updating a frontend review. SPECIFICATIONS As those widgets grow it is better to have them in separate files in order to better understand code organization. Future commits will improve composer behavior, notably in attachments management. LINKS Task 2066600 (manage attachments) Task 2058595 (eLearning v13 testing) --- addons/portal/static/src/js/portal_chatter.js | 154 +---------------- .../portal/static/src/js/portal_composer.js | 161 ++++++++++++++++++ addons/portal/views/assets.xml | 1 + .../static/src/js/portal_composer.js | 4 +- .../static/src/js/portal_rating_composer.js | 4 +- 5 files changed, 168 insertions(+), 156 deletions(-) create mode 100644 addons/portal/static/src/js/portal_composer.js diff --git a/addons/portal/static/src/js/portal_chatter.js b/addons/portal/static/src/js/portal_chatter.js index a2a089d2a96..0b23ec2c386 100644 --- a/addons/portal/static/src/js/portal_chatter.js +++ b/addons/portal/static/src/js/portal_chatter.js @@ -1,163 +1,14 @@ odoo.define('portal.chatter', function (require) { 'use strict'; -var ajax = require('web.ajax'); var core = require('web.core'); var publicWidget = require('web.public.widget'); var time = require('web.time'); +var portalComposer = require('portal.composer'); var qweb = core.qweb; var _t = core._t; -/** - * Widget PortalComposer - * - * Display the composer (according to access right) - * - */ -var PortalComposer = publicWidget.Widget.extend({ - template: 'portal.Composer', - xmlDependencies: ['/portal/static/src/xml/portal_chatter.xml'], - events: { - 'change .o_portal_chatter_file_input': '_onFileInputChange', - 'click .o_portal_chatter_attachment_btn': '_onAttachmentButtonClick', - 'click .o_portal_chatter_attachment_delete': 'async _onAttachmentDeleteClick', - 'click .o_portal_chatter_composer_btn': 'async _onSubmitButtonClick', - }, - - /** - * @constructor - */ - init: function (parent, options) { - this._super.apply(this, arguments); - this.options = _.defaults(options || {}, { - 'allow_composer': true, - 'display_composer': false, - 'csrf_token': odoo.csrf_token, - 'token': false, - 'res_model': false, - 'res_id': false, - }); - this.attachments = []; - }, - /** - * @override - */ - start: function () { - this.$attachmentButton = this.$('.o_portal_chatter_attachment_btn'); - this.$fileInput = this.$('.o_portal_chatter_file_input'); - this.$sendButton = this.$('.o_portal_chatter_composer_btn'); - this.$attachments = this.$('.o_portal_chatter_composer_form .o_portal_chatter_attachments'); - this.$attachmentIds = this.$('.o_portal_chatter_attachment_ids'); - this.$attachmentTokens = this.$('.o_portal_chatter_attachment_tokens'); - - return this._super.apply(this, arguments); - }, - - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- - - /** - * @private - */ - _onAttachmentButtonClick: function () { - this.$fileInput.click(); - }, - /** - * @private - * @param {Event} ev - * @returns {Promise} - */ - _onAttachmentDeleteClick: function (ev) { - var self = this; - var attachmentId = $(ev.currentTarget).closest('.o_portal_chatter_attachment').data('id'); - var accessToken = _.find(this.attachments, {'id': attachmentId}).access_token; - ev.preventDefault(); - ev.stopPropagation(); - - this.$sendButton.prop('disabled', true); - - return this._rpc({ - route: '/portal/attachment/remove', - params: { - 'attachment_id': attachmentId, - 'access_token': accessToken, - }, - }).then(function () { - self.attachments = _.reject(self.attachments, {'id': attachmentId}); - self._updateAttachments(); - self.$sendButton.prop('disabled', false); - }); - }, - /** - * @private - * @returns {Promise} - */ - _onFileInputChange: function () { - var self = this; - - this.$sendButton.prop('disabled', true); - - return Promise.all(_.map(this.$fileInput[0].files, function (file) { - return new Promise(function (resolve, reject) { - var data = { - 'name': file.name, - 'file': file, - 'res_id': self.options.res_id, - 'res_model': self.options.res_model, - 'access_token': self.options.token, - }; - ajax.post('/portal/attachment/add', data).then(function (attachment) { - self.attachments.push(attachment); - self._updateAttachments(); - resolve(); - }).guardedCatch(function (error) { - self.displayNotification({ - title: _t("Something went wrong."), - message: _.str.sprintf(_t("The file %s could not be saved."), - _.escape(file.name)), - type: 'warning', - sticky: true, - }); - resolve(); - }); - }); - })).then(function () { - self.$sendButton.prop('disabled', false); - }); - }, - /** - * Returns a Promise that is never resolved to prevent sending the form - * twice when clicking twice on the button, in combination with the `async` - * in the event definition. - * - * @private - * @returns {Promise} - */ - _onSubmitButtonClick: function () { - return new Promise(function (resolve, reject) {}); - }, - - //-------------------------------------------------------------------------- - // Private - //-------------------------------------------------------------------------- - - /** - * @private - */ - _updateAttachments: function () { - this.$attachmentIds.val(_.pluck(this.attachments, 'id')); - this.$attachmentTokens.val(_.pluck(this.attachments, 'access_token')); - this.$attachments.html(qweb.render('portal.Chatter.Attachments', { - attachments: this.attachments, - showDelete: true, - })); - }, -}); - - - /** * Widget PortalChatter * @@ -237,7 +88,7 @@ var PortalChatter = publicWidget.Widget.extend({ // instanciate and insert composer widget if (this.options['display_composer']) { - this._composer = new PortalComposer(this, this.options); + this._composer = new portalComposer.PortalComposer(this, this.options); defs.push(this._composer.replace(this.$('.o_portal_chatter_composer'))); } @@ -426,7 +277,6 @@ publicWidget.registry.portalChatter = publicWidget.Widget.extend({ }); return { - PortalComposer: PortalComposer, PortalChatter: PortalChatter, }; }); diff --git a/addons/portal/static/src/js/portal_composer.js b/addons/portal/static/src/js/portal_composer.js new file mode 100644 index 00000000000..ecd2d0cc6c1 --- /dev/null +++ b/addons/portal/static/src/js/portal_composer.js @@ -0,0 +1,161 @@ +odoo.define('portal.composer', function (require) { +'use strict'; + +var ajax = require('web.ajax'); +var core = require('web.core'); +var publicWidget = require('web.public.widget'); + +var qweb = core.qweb; +var _t = core._t; + +/** + * Widget PortalComposer + * + * Display the composer (according to access right) + * + */ +var PortalComposer = publicWidget.Widget.extend({ + template: 'portal.Composer', + xmlDependencies: ['/portal/static/src/xml/portal_chatter.xml'], + events: { + 'change .o_portal_chatter_file_input': '_onFileInputChange', + 'click .o_portal_chatter_attachment_btn': '_onAttachmentButtonClick', + 'click .o_portal_chatter_attachment_delete': 'async _onAttachmentDeleteClick', + 'click .o_portal_chatter_composer_btn': 'async _onSubmitButtonClick', + }, + + /** + * @constructor + */ + init: function (parent, options) { + this._super.apply(this, arguments); + this.options = _.defaults(options || {}, { + 'allow_composer': true, + 'display_composer': false, + 'csrf_token': odoo.csrf_token, + 'token': false, + 'res_model': false, + 'res_id': false, + }); + this.attachments = []; + }, + /** + * @override + */ + start: function () { + this.$attachmentButton = this.$('.o_portal_chatter_attachment_btn'); + this.$fileInput = this.$('.o_portal_chatter_file_input'); + this.$sendButton = this.$('.o_portal_chatter_composer_btn'); + this.$attachments = this.$('.o_portal_chatter_composer_form .o_portal_chatter_attachments'); + this.$attachmentIds = this.$('.o_portal_chatter_attachment_ids'); + this.$attachmentTokens = this.$('.o_portal_chatter_attachment_tokens'); + + return this._super.apply(this, arguments); + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + */ + _onAttachmentButtonClick: function () { + this.$fileInput.click(); + }, + /** + * @private + * @param {Event} ev + * @returns {Promise} + */ + _onAttachmentDeleteClick: function (ev) { + var self = this; + var attachmentId = $(ev.currentTarget).closest('.o_portal_chatter_attachment').data('id'); + var accessToken = _.find(this.attachments, {'id': attachmentId}).access_token; + ev.preventDefault(); + ev.stopPropagation(); + + this.$sendButton.prop('disabled', true); + + return this._rpc({ + route: '/portal/attachment/remove', + params: { + 'attachment_id': attachmentId, + 'access_token': accessToken, + }, + }).then(function () { + self.attachments = _.reject(self.attachments, {'id': attachmentId}); + self._updateAttachments(); + self.$sendButton.prop('disabled', false); + }); + }, + /** + * @private + * @returns {Promise} + */ + _onFileInputChange: function () { + var self = this; + + this.$sendButton.prop('disabled', true); + + return Promise.all(_.map(this.$fileInput[0].files, function (file) { + return new Promise(function (resolve, reject) { + var data = { + 'name': file.name, + 'file': file, + 'res_id': self.options.res_id, + 'res_model': self.options.res_model, + 'access_token': self.options.token, + }; + ajax.post('/portal/attachment/add', data).then(function (attachment) { + self.attachments.push(attachment); + self._updateAttachments(); + resolve(); + }).guardedCatch(function (error) { + self.displayNotification({ + title: _t("Something went wrong."), + message: _.str.sprintf(_t("The file %s could not be saved."), + _.escape(file.name)), + type: 'warning', + sticky: true, + }); + resolve(); + }); + }); + })).then(function () { + self.$sendButton.prop('disabled', false); + }); + }, + /** + * Returns a Promise that is never resolved to prevent sending the form + * twice when clicking twice on the button, in combination with the `async` + * in the event definition. + * + * @private + * @returns {Promise} + */ + _onSubmitButtonClick: function () { + return new Promise(function (resolve, reject) {}); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @private + */ + _updateAttachments: function () { + this.$attachmentIds.val(_.pluck(this.attachments, 'id')); + this.$attachmentTokens.val(_.pluck(this.attachments, 'access_token')); + this.$attachments.html(qweb.render('portal.Chatter.Attachments', { + attachments: this.attachments, + showDelete: true, + })); + }, +}); + +return { + PortalComposer: PortalComposer, +}; +}); diff --git a/addons/portal/views/assets.xml b/addons/portal/views/assets.xml index 73024f03a0d..2fbcf61da04 100644 --- a/addons/portal/views/assets.xml +++ b/addons/portal/views/assets.xml @@ -19,6 +19,7 @@ + diff --git a/addons/website_rating/static/src/js/portal_composer.js b/addons/website_rating/static/src/js/portal_composer.js index bd7aac7a94d..37b0b9e3511 100644 --- a/addons/website_rating/static/src/js/portal_composer.js +++ b/addons/website_rating/static/src/js/portal_composer.js @@ -2,11 +2,11 @@ odoo.define('rating.portal.composer', function (require) { 'use strict'; var core = require('web.core'); -var portalChatter = require('portal.chatter'); +var portalComposer = require('portal.composer'); var _t = core._t; -var PortalComposer = portalChatter.PortalComposer; +var PortalComposer = portalComposer.PortalComposer; var STAR_RATING_RATIO = 2; // conversion factor from the star (1-5) to the db rating range (1-10) diff --git a/addons/website_rating/static/src/js/portal_rating_composer.js b/addons/website_rating/static/src/js/portal_rating_composer.js index 78e6a4d4d1d..c73ea5d0f78 100644 --- a/addons/website_rating/static/src/js/portal_rating_composer.js +++ b/addons/website_rating/static/src/js/portal_rating_composer.js @@ -3,9 +3,9 @@ odoo.define('portal.rating.composer', function (require) { var publicWidget = require('web.public.widget'); var session = require('web.session'); -var portalChatter = require('portal.chatter'); +var portalComposer = require('portal.composer'); -var PortalComposer = portalChatter.PortalComposer; +var PortalComposer = portalComposer.PortalComposer; var STAR_RATING_RATIO = 2; // conversion factor from the star (1-5) to the db rating range (1-10)