[IMP] portal,website_rating: new popup composer to submit rating
Rating document available on a website will become more common, but we want to do it with different UI widget. This commit introduces a new "popup rating composer": the idea is the rating average is displayed with stars, and when clicking on it, a popup with the composer appears. The user can so submit its review. To do so, we factorize the Portal Composer into a dedicated widget (instead of natively inside Portal Chatter). Task-1902304
This commit is contained in:
@@ -12,6 +12,43 @@ var time = require('web.time');
|
||||
var qweb = core.qweb;
|
||||
var _t = core._t;
|
||||
|
||||
/**
|
||||
* Widget PortalComposer
|
||||
*
|
||||
* Display the composer (according to access right)
|
||||
*
|
||||
*/
|
||||
var PortalComposer = Widget.extend({
|
||||
template: 'portal.Composer',
|
||||
events: {
|
||||
'click .o_portal_chatter_composer_btn': '_onSubmitButtonClick',
|
||||
},
|
||||
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,
|
||||
});
|
||||
|
||||
// TODO simplify this using the 'async' keyword in the events
|
||||
// property definition as soon as this widget is converted in
|
||||
// frontend widget.
|
||||
this._onSubmitButtonClick = dom.makeButtonHandler(this._onSubmitButtonClick);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onSubmitButtonClick: function () {
|
||||
return $.Deferred();
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Widget PortalChatter
|
||||
*
|
||||
@@ -20,15 +57,23 @@ var _t = core._t;
|
||||
* - Provider API to filter displayed messages
|
||||
*/
|
||||
var PortalChatter = Widget.extend({
|
||||
template: 'portal.chatter',
|
||||
template: 'portal.Chatter',
|
||||
events: {
|
||||
"click .o_portal_chatter_pager_btn": '_onClickPager',
|
||||
'click .o_portal_chatter_composer_btn': '_onSubmitButtonClick',
|
||||
},
|
||||
xmlDependencies: ['/portal/static/src/xml/portal_chatter.xml'],
|
||||
|
||||
init: function(parent, options){
|
||||
var self = this;
|
||||
this.options = {};
|
||||
this._super.apply(this, arguments);
|
||||
this.options = _.defaults(options || {}, {
|
||||
|
||||
// underscorize the camelcased option keys
|
||||
_.each(options, function(val, key) {
|
||||
self.options[_.str.underscored(key)] = val;
|
||||
});
|
||||
// set default options
|
||||
this.options = _.defaults(this.options, {
|
||||
'allow_composer': true,
|
||||
'display_composer': false,
|
||||
'csrf_token': odoo.csrf_token,
|
||||
@@ -45,20 +90,16 @@ var PortalChatter = Widget.extend({
|
||||
this.set('pager', {});
|
||||
this.set('domain', this.options['domain']);
|
||||
this._current_page = this.options['pager_start'];
|
||||
|
||||
// TODO simplify this using the 'async' keyword in the events
|
||||
// property definition as soon as this widget is converted in
|
||||
// frontend widget.
|
||||
this._onSubmitButtonClick = dom.makeButtonHandler(this._onSubmitButtonClick);
|
||||
},
|
||||
willStart: function(){
|
||||
var self = this;
|
||||
// load qweb template and init data
|
||||
return $.when(
|
||||
this._super.apply(this, arguments),
|
||||
rpc.query({
|
||||
route: '/mail/chatter_init',
|
||||
params: this._messageFetchPrepareParams()
|
||||
}), this._loadTemplates()
|
||||
}),
|
||||
).then(function(result){
|
||||
self.result = result;
|
||||
self.options = _.extend(self.options, self.result['options'] || {});
|
||||
@@ -80,7 +121,18 @@ var PortalChatter = Widget.extend({
|
||||
// set options and parameters
|
||||
this.set('message_count', this.options['message_count']);
|
||||
this.set('messages', this.preprocessMessages(this.result['messages']));
|
||||
return this._super.apply(this, arguments);
|
||||
|
||||
|
||||
var defs = [];
|
||||
defs.push(this._super.apply(this, arguments));
|
||||
|
||||
// instanciate and insert composer widget
|
||||
if (this.options['display_composer']) {
|
||||
this._composer = new PortalComposer(this, this.options);
|
||||
defs.push(this._composer.replace(this.$('.o_portal_chatter_composer')));
|
||||
}
|
||||
|
||||
return $.when.apply($, defs);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -134,13 +186,6 @@ var PortalChatter = Widget.extend({
|
||||
var d = domain ? domain : _.clone(this.get('domain'));
|
||||
this.set('domain', d); // trigger fetch message
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @returns {Deferred}
|
||||
*/
|
||||
_loadTemplates: function(){
|
||||
return ajax.loadXML('/portal/static/src/xml/portal_chatter.xml', qweb);
|
||||
},
|
||||
_messageFetchPrepareParams: function(){
|
||||
var self = this;
|
||||
var data = {
|
||||
@@ -234,12 +279,6 @@ var PortalChatter = Widget.extend({
|
||||
var page = $(ev.currentTarget).data('page');
|
||||
this._changeCurrentPage(page);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onSubmitButtonClick: function () {
|
||||
return $.Deferred();
|
||||
},
|
||||
});
|
||||
|
||||
base.ready().then(function () {
|
||||
@@ -251,6 +290,7 @@ base.ready().then(function () {
|
||||
});
|
||||
|
||||
return {
|
||||
PortalComposer: PortalComposer,
|
||||
PortalChatter: PortalChatter,
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,12 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="portal.chatter_composer">
|
||||
<!--
|
||||
Widget PortalComposer (standalone)
|
||||
|
||||
required many options: token, res_model, res_id, ...
|
||||
-->
|
||||
<t t-name="portal.Composer">
|
||||
<div class="o_portal_chatter_composer" t-if="widget.options['allow_composer']">
|
||||
<t t-if="!widget.options['display_composer']">
|
||||
<h4>Leave a comment</h4>
|
||||
@@ -45,13 +50,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
<hr/>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!--
|
||||
Widget PortalChatter, and subtemplates
|
||||
-->
|
||||
|
||||
<t t-name="portal.chatter_messages">
|
||||
<div class="o_portal_chatter_messages">
|
||||
<t t-foreach="widget.get('messages')" t-as="message">
|
||||
<t t-foreach="widget.get('messages') || []" t-as="message">
|
||||
<div class="media o_portal_chatter_message" t-att-id="'message-' + message.id">
|
||||
<img class="o_portal_chatter_avatar" t-att-src="message.author_avatar_url" alt="avatar"/>
|
||||
<div class="media-body">
|
||||
@@ -96,13 +104,14 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<t t-name="portal.chatter">
|
||||
<t t-name="portal.Chatter">
|
||||
<div class="o_portal_chatter p-0">
|
||||
<div class="o_portal_chatter_header">
|
||||
<t t-call="portal.chatter_message_count"/>
|
||||
</div>
|
||||
<hr t-if="widget.options['allow_composer']"/>
|
||||
<div class="o_portal_chatter_composer"/>
|
||||
<hr/>
|
||||
<t t-call="portal.chatter_composer"/>
|
||||
<t t-call="portal.chatter_messages"/>
|
||||
<div class="o_portal_chatter_footer">
|
||||
<t t-call="portal.pager"/>
|
||||
|
||||
@@ -1,27 +1,122 @@
|
||||
odoo.define('website_rating.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 rootWidget = require('web_editor.root_widget');
|
||||
|
||||
var session = require('web.session');
|
||||
|
||||
var qweb = core.qweb;
|
||||
var _t = core._t;
|
||||
|
||||
var PortalComposer = require('portal.chatter').PortalComposer;
|
||||
var PortalChatter = require('portal.chatter').PortalChatter;
|
||||
|
||||
/**
|
||||
* Extends Frontend Chatter to handle rating
|
||||
* PortalComposer
|
||||
*
|
||||
* Extends Frontend Composer to handle rating submission
|
||||
*/
|
||||
PortalChatter.include({
|
||||
events: _.extend({}, PortalChatter.prototype.events, {
|
||||
PortalComposer.include({
|
||||
events: _.extend({}, PortalComposer.prototype.events, {
|
||||
"mousemove .stars i" : "_onMoveStar",
|
||||
"mouseleave .stars i" : "_onMoveOutStar",
|
||||
"click .stars" : "_onClickStar",
|
||||
"mouseleave .stars" : "_onMouseleaveStar",
|
||||
}),
|
||||
|
||||
init: function(parent, options){
|
||||
this._super.apply(this, arguments);
|
||||
// star input widget
|
||||
this.labels = {
|
||||
'0': "",
|
||||
'1': _t("I hate it"),
|
||||
'2': _t("I don't like it"),
|
||||
'3': _t("It's okay"),
|
||||
'4': _t("I like it"),
|
||||
'5': _t("I love it"),
|
||||
};
|
||||
this.user_click = false; // user has click or not
|
||||
this.set("star_value", this.options.rating_default_value);
|
||||
this.on("change:star_value", this, this._onChangeStarValue);
|
||||
},
|
||||
start: function(){
|
||||
var self = this;
|
||||
return this._super.apply(this, arguments).then(function(){
|
||||
// rating stars
|
||||
self.$input = self.$('input[name="rating_value"]');
|
||||
self.$star_list = self.$('.stars').find('i');
|
||||
self.set("star_value", self.options.rating_default_value); // set the default value to trigger the display of star widget
|
||||
});
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
_onClickStar: function(e){
|
||||
this.user_click = true;
|
||||
this.$input.val(this.get("star_value"));
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onChangeStarValue: function(){
|
||||
var val = this.get("star_value");
|
||||
var index = Math.floor(val);
|
||||
var decimal = val - index;
|
||||
// reset the stars
|
||||
this.$star_list.removeClass('fa-star fa-star-half-o').addClass('fa-star-o');
|
||||
|
||||
this.$('.stars').find("i:lt("+index+")").removeClass('fa-star-o fa-star-half-o').addClass('fa-star');
|
||||
if(decimal){
|
||||
this.$('.stars').find("i:eq("+(index)+")").removeClass('fa-star-o fa-star fa-star-half-o').addClass('fa-star-half-o');
|
||||
}
|
||||
|
||||
this.$('.rate_text .label').text(this.labels[index]);
|
||||
},
|
||||
_onMouseleaveStar: function(e){
|
||||
this.$('.rate_text').hide();
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
_onMoveStar: function(e){
|
||||
var index = this.$('.stars i').index(e.currentTarget);
|
||||
this.$('.rate_text').show();
|
||||
this.set("star_value", index+1);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onMoveOutStar: function(){
|
||||
if(!this.user_click){
|
||||
this.set("star_value", parseInt(this.$input.val()));
|
||||
}
|
||||
this.user_click = false;
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* PortalChatter
|
||||
*
|
||||
* Extends Frontend Chatter to handle rating
|
||||
*/
|
||||
PortalChatter.include({
|
||||
events: _.extend({}, PortalChatter.prototype.events, {
|
||||
"click .o_website_rating_select": "_onClickStarDomain",
|
||||
"click .o_website_rating_select_text": "_onClickStarDomainReset",
|
||||
}),
|
||||
xmlDependencies: (PortalChatter.prototype.xmlDependencies || []).concat(['/website_rating/static/src/xml/website_mail.xml', '/website_rating/static/src/xml/portal_chatter.xml']),
|
||||
|
||||
init: function(parent, options){
|
||||
this._super.apply(this, arguments);
|
||||
@@ -36,18 +131,6 @@ odoo.define('website_rating.thread', function(require) {
|
||||
this.set('rating_card_values', {});
|
||||
this.set('rating_value', false);
|
||||
this.on("change:rating_value", this, this._onChangeRatingDomain);
|
||||
// rating star
|
||||
this.labels = {
|
||||
'0': "",
|
||||
'1': _t("I hate it"),
|
||||
'2': _t("I don't like it"),
|
||||
'3': _t("It's okay"),
|
||||
'4': _t("I like it"),
|
||||
'5': _t("I love it"),
|
||||
};
|
||||
this.user_click = false; // user has click or not
|
||||
this.set("star_value", this.options.rating_default_value);
|
||||
this.on("change:star_value", this, this._onChangeStarValue);
|
||||
},
|
||||
willStart: function(){
|
||||
var self = this;
|
||||
@@ -70,15 +153,6 @@ odoo.define('website_rating.thread', function(require) {
|
||||
}
|
||||
});
|
||||
},
|
||||
start: function(){
|
||||
var self = this;
|
||||
return this._super.apply(this, arguments).then(function(){
|
||||
// rating stars
|
||||
self.$input = self.$('input[name="rating_value"]');
|
||||
self.$star_list = self.$('.stars').find('i');
|
||||
self.set("star_value", self.options.rating_default_value); // set the default value to trigger the display of star widget
|
||||
});
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
@@ -129,9 +203,6 @@ odoo.define('website_rating.thread', function(require) {
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
_loadTemplates: function(){
|
||||
return $.when(this._super(), ajax.loadXML('/website_rating/static/src/xml/website_mail.xml', qweb));
|
||||
},
|
||||
_messageFetchPrepareParams: function(){
|
||||
var params = this._super.apply(this, arguments);
|
||||
if(this.options['display_rating']){
|
||||
@@ -144,14 +215,6 @@ odoo.define('website_rating.thread', function(require) {
|
||||
// Handlers
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} event
|
||||
*/
|
||||
_onClickStar: function(e){
|
||||
this.user_click = true;
|
||||
this.$input.val(this.get("star_value"));
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} event
|
||||
@@ -179,6 +242,7 @@ odoo.define('website_rating.thread', function(require) {
|
||||
*/
|
||||
_onClickStarDomainReset: function(e){
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
this.set('rating_value', false);
|
||||
this.$('.o_website_rating_select_text').css('visibility', 'hidden');
|
||||
this.$('.o_website_rating_select').css({
|
||||
@@ -195,43 +259,62 @@ odoo.define('website_rating.thread', function(require) {
|
||||
}
|
||||
this._changeCurrentPage(1, domain);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onChangeStarValue: function(){
|
||||
var val = this.get("star_value");
|
||||
var index = Math.floor(val);
|
||||
var decimal = val - index;
|
||||
// reset the stars
|
||||
this.$star_list.removeClass('fa-star fa-star-half-o').addClass('fa-star-o');
|
||||
});
|
||||
|
||||
this.$('.stars').find("i:lt("+index+")").removeClass('fa-star-o fa-star-half-o').addClass('fa-star');
|
||||
if(decimal){
|
||||
this.$('.stars').find("i:eq("+(index)+")").removeClass('fa-star-o fa-star fa-star-half-o').addClass('fa-star-half-o');
|
||||
}
|
||||
|
||||
this.$('.rate_text .label').text(this.labels[index]);
|
||||
},
|
||||
_onMouseleaveStar: function(e){
|
||||
this.$('.rate_text').hide();
|
||||
/**
|
||||
* RatingPopupComposer
|
||||
*
|
||||
* Display the rating average with a static star widget, and open
|
||||
* a popup with the portal composer when clicking on it.
|
||||
**/
|
||||
var RatingPopupComposer = Widget.extend({
|
||||
template: 'website_rating.PopupComposer',
|
||||
xmlDependencies: [
|
||||
'/portal/static/src/xml/portal_chatter.xml',
|
||||
'/website_rating/static/src/xml/website_mail.xml',
|
||||
'/website_rating/static/src/xml/portal_chatter.xml',
|
||||
],
|
||||
|
||||
init: function(parent, options){
|
||||
this._super.apply(this, arguments);
|
||||
this.rating_avg = Math.round(options['ratingAvg'] * 100) / 100 || 0.0;
|
||||
this.rating_total = options['ratingTotal'] || 0.0;
|
||||
|
||||
this.options = _.defaults({}, options, {
|
||||
'token': false,
|
||||
'res_model': false,
|
||||
'res_id': false,
|
||||
'pid': 0,
|
||||
'display_composer': !session.is_website_user,
|
||||
'display_rating': true,
|
||||
'csrf_token': odoo.csrf_token,
|
||||
'user_id': session.user_id,
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
* @param {MouseEvent} event
|
||||
* @override
|
||||
*/
|
||||
_onMoveStar: function(e){
|
||||
var index = this.$('.stars i').index(e.currentTarget);
|
||||
this.$('.rate_text').show();
|
||||
this.set("star_value", index+1);
|
||||
},
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_onMoveOutStar: function(){
|
||||
if(!this.user_click){
|
||||
this.set("star_value", parseInt(this.$input.val()));
|
||||
}
|
||||
this.user_click = false;
|
||||
start: function () {
|
||||
var defs = [];
|
||||
defs.push(this._super.apply(this, arguments));
|
||||
|
||||
// instanciate and insert composer widget
|
||||
this._composer = new PortalComposer(this, this.options);
|
||||
defs.push(this._composer.replace(this.$('.o_portal_chatter_composer')));
|
||||
|
||||
return $.when.apply($, defs);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
base.ready().then(function () {
|
||||
$('.o_rating_popup_composer').each(function (index) {
|
||||
var $elem = $(this);
|
||||
var rating_popup = new RatingPopupComposer(rootWidget, $elem.data());
|
||||
rating_popup.appendTo($elem);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
@@ -68,3 +68,15 @@ $o-w-rating-star-color: #FACC2E;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
/* Rating Popup Composer */
|
||||
.o_rating_popup_composer {
|
||||
|
||||
.o_rating_clickable {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.o_portal_chatter_avatar {
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<!--
|
||||
Inherited templates from portal to custom chatter with rating
|
||||
-->
|
||||
<t t-extend="portal.Composer">
|
||||
<t t-jquery=".o_portal_chatter_composer_form input[name='csrf_token']" t-operation="after">
|
||||
<t t-call="website_rating.rating_star_input"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-extend="portal.chatter_messages">
|
||||
<t t-jquery="t[t-raw='message.body']" t-operation="before">
|
||||
<t t-if="message['rating_value']">
|
||||
<t t-call="website_rating.rating_stars_static">
|
||||
<t t-set="val" t-value="message.rating_value"/>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-extend="portal.Chatter">
|
||||
<t t-jquery="t[t-call='portal.chatter_message_count']" t-operation="replace">
|
||||
<t t-if="widget.options['display_rating']">
|
||||
<t t-call="website_rating.rating_card"/>
|
||||
</t>
|
||||
<t t-if="!widget.options['display_rating']">
|
||||
<t t-call="portal.chatter_message_count"/>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
|
||||
<!--
|
||||
Popup Rating Composer Widget
|
||||
-->
|
||||
<t t-name="website_rating.PopupComposer">
|
||||
<div>
|
||||
<button t-if="widget.options['display_composer']" type="button" class="btn btn-primary" data-toggle="modal" data-target="#ratingpopupcomposer">
|
||||
<t t-if="widget.options['display_composer']">Add a review</t>
|
||||
</button>
|
||||
<div>
|
||||
<t t-call="website_rating.rating_stars_static">
|
||||
<t t-set="val" t-value="widget.rating_avg || 0"/>
|
||||
<t t-set="inline_mode" t-value="true"/>
|
||||
</t>
|
||||
<t t-if="widget.rating_total">
|
||||
<t t-esc="widget.rating_avg"/> (<t t-esc="widget.rating_total"/>)
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div t-if="widget.options['display_composer']" class="modal fade" id="ratingpopupcomposer" tabindex="-1" role="dialog" aria-labelledby="ratingpopupcomposerlabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="ratingpopupcomposerlabel">Add a review</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span>&times;</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="o_portal_chatter_composer"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
@@ -5,7 +5,7 @@
|
||||
<t t-set="val_integer" t-value="Math.floor(val)"/>
|
||||
<t t-set="val_decimal" t-value="val - val_integer"/>
|
||||
<t t-set="empty_star" t-value="5 - (val_integer+Math.ceil(val_decimal))"/>
|
||||
<div class="o_website_rating_static">
|
||||
<div class="o_website_rating_static" t-att-style="inline_mode ? 'display:inline' : ''">
|
||||
<t t-foreach="_.range(0, val_integer)" t-as="num">
|
||||
<i class="fa fa-star" role="img" aria-label="One star" title="One star"></i>
|
||||
</t>
|
||||
@@ -75,34 +75,4 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<!--
|
||||
Inherited templates from portal to custom chatter with rating
|
||||
-->
|
||||
<t t-extend="portal.chatter_composer">
|
||||
<t t-jquery=".o_portal_chatter_composer_form input[name='csrf_token']" t-operation="after">
|
||||
<t t-call="website_rating.rating_star_input"/>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-extend="portal.chatter_messages">
|
||||
<t t-jquery="t[t-raw='message.body']" t-operation="before">
|
||||
<t t-if="message['rating_value']">
|
||||
<t t-call="website_rating.rating_stars_static">
|
||||
<t t-set="val" t-value="message.rating_value"/>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
<t t-extend="portal.chatter">
|
||||
<t t-jquery="t[t-call='portal.chatter_message_count']" t-operation="replace">
|
||||
<t t-if="widget.options['display_rating']">
|
||||
<t t-call="website_rating.rating_card"/>
|
||||
</t>
|
||||
<t t-if="!widget.options['display_rating']">
|
||||
<t t-call="portal.chatter_message_count"/>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
||||
@@ -38,4 +38,19 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!--
|
||||
Display static star widget, and open rating composer on click
|
||||
This template provide the container of the Popup Rating Composer. The rest is done in js.
|
||||
To use this template, you need to call it after setting the following variable in your template or in your controller:
|
||||
:float rating_avg : average rating to be displayed with star widget
|
||||
:object browserecord : the mail_thread object
|
||||
:token string (optional): if you want your chatter to be available for non-logged user,
|
||||
you can use a token to verify the identity of the user;
|
||||
the message will be posted with the identity of the partner_id of the object
|
||||
-->
|
||||
<template id="rating_stars_static_popup_composer" name="Rating: rating composer in popup">
|
||||
<div class="row d-print-none o_rating_popup_composer o_not_editable p-0" t-att-data-rating-avg="rating_avg or 0.0" t-att-data-rating-total="rating_total or 0.0" t-att-data-token="token" t-att-data-hash="hash" t-att-data-pid="pid" t-att-data-res_model="object._name" t-att-data-res_id="object.id" t-att-data-partner_id="request.env.user.partner_id.id">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
||||
Reference in New Issue
Block a user