[MOV] portal,website_mail: move chatter frontend to portal

This split responsiblilies :
- portal provides basic chatter for portal document, and
website documents (slides, blog, ...).
- website_mail provides comments moderation (unpublished mail
message)
- website_rating integrate rating when posting comments
This commit is contained in:
Jérome Maes
2017-08-16 14:56:40 +02:00
parent 2972976962
commit 3cfd64f63f
31 changed files with 594 additions and 539 deletions
@@ -2,37 +2,3 @@
.js_follow[data-follow='off'] .js_unfollow_btn {
display: none;
}
.o_website_mail_chatter {
padding: 10px;
.o_website_mail_avatar{
width: 45px;
height: 45px;
}
.o_website_mail_header {
margin-bottom: 15px;
}
.o_website_mail_composer {
margin-bottom: 15px;
}
.o_website_mail_messages {
margin-bottom: 15px;
.o_website_mail_message_title {
p {
font-size:85%;
color:@odoo-main-color-muted;
margin: 0px;
}
}
}
.o_website_mail_pager {
text-align: center;
}
}
@@ -1,237 +1,20 @@
odoo.define('website_mail.thread', function (require) {
odoo.define('website_mail.thread', function(require) {
'use strict';
var base = require('web_editor.base');
var ajax = require('web.ajax');
var core = require('web.core');
var Widget = require('web.Widget');
var rpc = require('web.rpc');
var qweb = core.qweb;
var _t = core._t;
var PortalChatter = require('portal.chatter').PortalChatter;
/**
* Widget WebsiteMailThread
*
* - Fetch message fron controller
* - Display chatter: pager, total message, composer (according to access right)
* - Provider API to filter displayed messages
* Extends Frontend Chatter to handle rating
*/
var WebsiteMailThread = Widget.extend({
template: 'website_mail.chatter',
events: {
"click .o_website_mail_pager_btn": '_onClickPager'
},
init: function (parent, options){
this._super.apply(this, arguments);
this.options = _.defaults(options || {}, {
'allow_composer': true,
'display_composer': false,
'csrf_token': odoo.csrf_token,
'message_count': 0,
'pager_step': 10,
'pager_scope': 5,
'pager_start': 1,
'is_user_public': true,
'is_user_publisher': false,
'domain': [],
});
this.set('messages', []);
this.set('message_count', this.options['message_count']);
this.set('pager', {});
this.set('domain', this.options['domain']);
this._current_page = this.options['pager_start'];
},
willStart: function (){
var self = this;
// load qweb template and init data
return $.when(
rpc.query({
route: '/website_mail/init',
params: this._messageFetchPrepareParams()
}), this._loadTemplates()
).then(function (result){
// bind events
self.on("change:messages", self, self._renderMessages);
self.on("change:message_count", self, function () {
self._renderMessageCount();
self.set('pager', self._pager(self._current_page));
});
self.on("change:pager", self, self._renderPager);
self.on("change:domain", self, self._onChangeDomain);
// set options and parameters
self.options = _.extend(self.options, result['options'] || {});
self.set('message_count', self.options['message_count']);
self.set('messages', self.preprocessMessages(result['messages']));
return result;
});
},
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
/**
* Fetch the messages and the message count from the server for the
* current page and current domain.
*
* @param {Array}
* @returns {Deferred}
*/
messageFetch: function (domain){
var self = this;
return rpc.query({
route: '/website_mail/fetch',
params: self._messageFetchPrepareParams()
}).then(function (result){
self.set('messages', self.preprocessMessages(result['messages']));
self.set('message_count', result['message_count']);
});
},
/**
* Update the messages format
*
* @param {Array<Object>}
* @returns {Array}
*/
preprocessMessages: function (messages){
_.each(messages, function (m){
m['author_avatar_url'] = _.str.sprintf('/web/image/%s/%s/author_avatar/50x50', 'mail.message', m.id);
m['published_date_str'] = _.str.sprintf(_t('Published on %s'), moment(m.date).format('MMMM Do YYYY, h:mm:ss a'));
});
return messages;
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
/**
* Change the current page by refreshing current domain
*
* @private
* @param {Number} page
* @param {Array} domain
*/
_changeCurrentPage: function (page, domain){
this._current_page = page;
var d = domain ? domain : _.clone(this.get('domain'));
this.set('domain', d); // trigger fetch message
},
/**
* @private
* @returns {Deferred}
*/
_loadTemplates: function () {
return ajax.loadXML('/website_mail/static/src/xml/website_mail.xml', qweb);
},
_messageFetchPrepareParams: function () {
var self = this;
var data = {
'res_model': this.options['res_model'],
'res_id': this.options['res_id'],
'limit': this.options['pager_step'],
'offset': (this._current_page-1) * this.options['pager_step'],
'allow_composer': this.options['allow_composer'],
};
// add fields to allow to post comment without being logged
_.each(['token', 'token_field'], function (field) {
if (self.options[field]){
data[field] = self.options[field];
}
});
// add domain
if (this.get('domain')){
data['domain'] = this.get('domain');
}
return data;
},
/**
* Generate the pager data for the given page number
*
* @private
* @param {Number} page
* @returns {Object}
*/
_pager: function (page) {
page = page || 1;
var total = this.get('message_count');
var scope = this.options['pager_scope'];
var step = this.options['pager_step'];
// Compute Pager
var page_count = Math.ceil(parseFloat(total) / step);
page = Math.max(1, Math.min(parseInt(page), page_count));
scope -= 1;
var pmin = Math.max(page - parseInt(Math.floor(scope/2)), 1);
var pmax = Math.min(pmin + scope, page_count);
if (pmax - scope > 0){
pmin = pmax - scope;
} else {
pmin = 1;
}
var pages = [];
_.each(_.range(pmin, pmax+1), function (index) {
pages.push(index);
});
return {
"page_count": page_count,
"offset": (page - 1) * step,
"page": page,
"page_start": pmin,
"page_previous": Math.max(pmin, page - 1),
"page_next": Math.min(pmax, page + 1),
"page_end": pmax,
"pages": pages
};
},
_renderMessages: function () {
this.$('.o_website_mail_messages').html(qweb.render("website_mail.chatter_messages", {widget: this}));
},
_renderMessageCount: function () {
this.$('.o_message_counter').replaceWith(qweb.render("website_mail.chatter_message_count", {widget: this}));
},
_renderPager: function () {
this.$('.o_website_mail_pager').replaceWith(qweb.render("website_mail.pager", {widget: this}));
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
_onChangeDomain: function () {
var self = this;
this.messageFetch().then(function () {
var p = self.get('current_page');
self.set('pager', self._pager(p));
});
},
/**
* @private
* @param {MouseEvent} event
*/
_onClickPager: function (ev) {
ev.preventDefault();
var page = $(ev.currentTarget).data('page');
this._changeCurrentPage(page);
PortalChatter.include({
_loadTemplates: function(){
return $.when(this._super(), ajax.loadXML('/website_mail/static/src/xml/website_mail.xml', qweb));
},
});
base.ready().then(function () {
$('.o_website_mail_thread').each(function (index) {
var $elem = $(this);
var mail_thread = new WebsiteMailThread(null, $elem.data());
mail_thread.appendTo($elem);
});
});
return {
WebsiteMailThread: WebsiteMailThread,
};
});
@@ -9,124 +9,15 @@
</t>
</t>
<t t-name="website_mail.chatter_message_count">
<t t-set="count" t-value="widget.get('message_count')"/>
<div class="o_message_counter">
<t t-if="count">
<span class="o_message_count fa fa-comments"> <t t-esc="count"/></span>
<t t-if="count == 1">comment</t>
<t t-else="">comments</t>
<t t-extend="portal.chatter_messages">
<t t-jquery=".o_portal_chatter_message_title" t-operation="before">
<t t-call="website_mail.publish_short">
<t t-set="res_model" t-value="'mail.message'"/>
<t t-set="res_id" t-value="message.id"/>
<t t-set="object" t-value="message"/>
<t t-set="is_publisher" t-value="widget.options['is_user_publisher']"/>
</t>
<t t-else="">
There are no comments for now.
</t>
</div>
</t>
</t>
<t t-name="website_mail.chatter_composer">
<div class="o_website_mail_composer" t-if="widget.options['allow_composer']">
<t t-if="!widget.options['display_composer']">
<h4>Leave a comment</h4>
<p>You must be <a t-attf-href="/web/login?redirect=#{window.encodeURI(window.location.href + '#discussion')}">logged in</a> to post a comment.</p>
</t>
<t t-if="widget.options['display_composer']">
<div class="media">
<div class="media-left">
<img class="o_website_mail_avatar pull-left" t-attf-src="/web/image/res.partner/#{widget.options['partner_id']}/image_small/50x50"/>
</div>
<div class="media-body">
<form class="o_website_mail_composer_form" t-attf-action="/website_mail/post/post" method="POST">
<input type="hidden" name="csrf_token" t-att-value="widget.options['csrf_token']"/>
<div class="mb32">
<textarea rows="4" name="message" class="form-control" placeholder="Write a message..."></textarea>
<input type='hidden' name="res_model" t-att-value="widget.options['res_model']"/>
<input type='hidden' name="res_id" t-att-value="widget.options['res_id']"/>
<input type='hidden' name="token" t-att-value="widget.options['token']" t-if="widget.options['token']"/>
<input type='hidden' name="sha_in" t-att-value="widget.options['sha_in']" t-if="widget.options['sha_in']"/>
<input type='hidden' name="sha_time" t-att-value="widget.options['sha_time']" t-if="widget.options['sha_time']"/>
<input type='hidden' name="token_field" t-att-value="widget.options['token_field']" t-if="widget.options['token_field']"/>
<div class="alert alert-danger mt8 mb0 o_website_mail_composer_error" style="display:none;">
Oops! Something went wrong. Try to reload the page and log in.
</div>
<button t-attf-class="o_website_mail_composer_btn btn btn-primary mt8 o_website_message_post_helper" type="submit">Send</button>
</div>
</form>
</div>
</div>
</t>
<hr/>
</div>
</t>
<t t-name="website_mail.chatter_messages">
<div class="o_website_mail_messages">
<t t-foreach="widget.get('messages')" t-as="message">
<div class="media o_website_mail_message" t-att-id="'message-' + message.id">
<div class="media-left">
<img class="media-object o_website_mail_avatar" t-att-src="message.author_avatar_url" alt="avatar"/>
</div>
<div class="media-body">
<t t-call="website_mail.publish_short">
<t t-set="res_model" t-value="'mail.message'"/>
<t t-set="res_id" t-value="message.id"/>
<t t-set="object" t-value="message"/>
<t t-set="is_publisher" t-value="widget.options['is_user_publisher']"/>
</t>
<div class="o_website_mail_message_title">
<h5 class="media-heading">
<t t-esc="message.author_id[1]"/>
</h5>
<p class="o_website_mail_puslished_date"><t t-esc="message.published_date_str"/></p>
</div>
<t t-raw="message.body"/>
<div class="o_website_mail_attachments">
<div class="col-md-2 col-sm-3 text-center" t-foreach='message.attachment_ids' t-as='attachment'>
<a t-attf-href="/web/content/#{attachment.id}?download=true" target="_blank">
<div class='oe_attachment_embedded o_image' t-att-title="attachment.name" t-att-data-mimetype="attachment.mimetype" t-attf-data-src="/web/image/#{attachment.id}/100x80"/>
<div class='oe_attachment_name'><t t-raw='attachment.name'/></div>
</a>
</div>
</div>
</div>
</div>
</t>
</div>
</t>
<t t-name="website_mail.pager">
<div class="o_website_mail_pager">
<t t-if="!_.isEmpty(widget.get('pager'))">
<ul class="pagination" t-if="widget.get('pager')['pages'].length &gt; 1">
<li t-if="widget.get('pager')['page'] != widget.get('pager')['page_previous']" t-att-data-page="widget.get('pager')['page_previous']" class="o_website_mail_pager_btn">
<a href="#"><i class="fa fa-chevron-left"/></a>
</li>
<t t-foreach="widget.get('pager')['pages']" t-as="page">
<li t-att-data-page="page" t-att-class="page == widget.get('pager')['page'] ? 'o_website_mail_pager_btn active' : 'o_website_mail_pager_btn'">
<a href="#"><t t-esc="page"/></a>
</li>
</t>
<li t-if="widget.get('pager')['page'] != widget.get('pager')['page_next']" t-att-data-page="widget.get('pager')['page_next']" class="o_website_mail_pager_btn">
<a href="#"><i class="fa fa-chevron-right"/></a>
</li>
</ul>
</t>
</div>
</t>
<t t-name="website_mail.chatter">
<div class="o_website_mail_chatter">
<div class="o_website_mail_header">
<t t-call="website_mail.chatter_message_count"/>
</div>
<hr/>
<t t-call="website_mail.chatter_composer"/>
<t t-call="website_mail.chatter_messages"/>
<div class="o_website_mail_footer">
<t t-call="website_mail.pager"/>
</div>
</div>
</t>
</templates>