Skip to content
Snippets Groups Projects
Commit bb197b1f authored by Thibault Delavallée's avatar Thibault Delavallée
Browse files

[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)
parent a6447663
Branches
Tags
No related merge requests found
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 <strong>%s</strong> 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,
};
});
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 <strong>%s</strong> 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,
};
});
......@@ -19,6 +19,7 @@
<xpath expr="//script[last()]" position="after">
<script type="text/javascript" src="/portal/static/src/js/portal.js"></script>
<script type="text/javascript" src="/portal/static/src/js/portal_chatter.js"></script>
<script type="text/javascript" src="/portal/static/src/js/portal_composer.js"></script>
<script type="text/javascript" src="/portal/static/src/js/portal_signature.js"></script>
<script type="text/javascript" src="/portal/static/src/js/portal_sidebar.js"></script>
</xpath>
......
......@@ -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)
......
......@@ -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)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment