[MERGE] portal, website_{mail, rating}: fix frontend rating and reorganize portal chatter overrides

PURPOSE

Fix frontend rating and clean a bit module organization.

SPECIFICATIONS

Fix rating in frontend (website_slides, website_sale): rating is halved at each
update and new entries have no rating.

Also reorganize portal chatter overrides

* rename files to ease code reading and discovering;
* move assets in their own file to better understand modules;
* move rating widget in its own file;

LINKS

Task 2057301
PR #35870

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Robot Odoo
2019-08-21 17:25:47 +02:00
committed by GitHub
19 changed files with 187 additions and 197 deletions
+12 -10
View File
@@ -85,6 +85,9 @@ def _message_post_helper(res_model, res_id, message, token='', _hash=False, pid=
class PortalChatter(http.Controller):
def _portal_post_filter_params(self):
return ['token', 'hash', 'pid']
@http.route(['/mail/chatter_post'], type='http', methods=['POST'], auth='public', website=True)
def portal_chatter_post(self, res_model, res_id, message, redirect=None, attachment_ids='', attachment_tokens='', **kw):
"""Create a new `mail.message` with the given `message` and/or
@@ -112,16 +115,15 @@ class PortalChatter(http.Controller):
# message is received in plaintext and saved in html
if message:
message = plaintext2html(message)
message = _message_post_helper(
res_model=res_model,
res_id=res_id,
token=kw.get('token'),
_hash=kw.get('hash'),
pid=kw.get('pid'),
message=message,
send_after_commit=False,
attachment_ids=attachment_ids
)
post_values = {
'res_model': res_model,
'res_id': res_id,
'message': message,
'send_after_commit': False,
'attachment_ids': attachment_ids,
}
post_values.update((fname, kw.get(fname)) for fname in self._portal_post_filter_params())
message = _message_post_helper(**post_values)
return request.redirect(url)
+1 -4
View File
@@ -12,13 +12,10 @@ It is responsible of comments moderation for published documents (forum, slides,
""",
'depends': ['website', 'mail'],
'data': [
'views/assets.xml',
'views/website_mail_templates.xml',
'data/mail_channel_data.xml',
'security/website_mail_security.xml',
],
'qweb': [
'static/src/xml/website_mail.xml'
],
'installable': True,
'auto_install': True,
}
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="channel_public" model="mail.channel">
<field name="name">Discussion Group</field>
<field name="public">public</field>
<field name="description">Public Discussion Group</field>
</record>
</data>
</odoo>
@@ -8,6 +8,6 @@ var portalChatter = require('portal.chatter');
*/
portalChatter.PortalChatter.include({
xmlDependencies: (portalChatter.PortalChatter.prototype.xmlDependencies || [])
.concat(['/website_mail/static/src/xml/website_mail.xml']),
.concat(['/website_mail/static/src/xml/portal_chatter.xml']),
});
});
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="head" inherit_id="website.assets_frontend" name="Mail customization">
<xpath expr="." position="inside">
<script type="text/javascript" src="/website_mail/static/src/js/follow.js"></script>
<script type="text/javascript" src="/website_mail/static/src/js/portal_chatter.js"></script>
<link rel="stylesheet" type="text/scss" href="/website_mail/static/src/css/website_mail.scss"/>
</xpath>
</template>
</odoo>
@@ -16,13 +16,4 @@
</div>
</div>
</template>
<template id="head" inherit_id="website.assets_frontend" name="Mail customization">
<xpath expr="." position="inside">
<script type="text/javascript" src="/website_mail/static/src/js/follow.js"></script>
<script type="text/javascript" src="/website_mail/static/src/js/website_mail.js"></script>
<link rel="stylesheet" type="text/scss" href="/website_mail/static/src/css/website_mail.scss"/>
</xpath>
</template>
</odoo>
+3 -2
View File
@@ -10,8 +10,9 @@ Bridge module for rating on website stuff.
""",
'depends': ['rating', 'website_mail'],
'data': [
'views/website_rating_templates.xml',
'views/assets.xml',
'views/portal_templates.xml',
'views/rating_templates.xml',
],
'qweb': ['static/src/xml/*.xml'],
'auto_install': True,
}
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import website_mail
from . import portal_chatter
@@ -7,11 +7,16 @@ from odoo.http import request
from odoo.addons.portal.controllers.mail import PortalChatter
class WebsiteRating(PortalChatter):
class PortalChatter(PortalChatter):
def _portal_post_filter_params(self):
fields = super(PortalChatter, self)._portal_post_filter_params()
fields.append('rating_value')
return fields
@http.route()
def portal_chatter_init(self, res_model, res_id, domain=False, limit=False, **kwargs):
result = super(WebsiteRating, self).portal_chatter_init(res_model, res_id, domain=domain, limit=limit, **kwargs)
result = super(PortalChatter, self).portal_chatter_init(res_model, res_id, domain=domain, limit=limit, **kwargs)
# get the rating statistics about the record
if kwargs.get('rating_include'):
record = request.env[res_model].browse(res_id)
@@ -26,4 +31,4 @@ class WebsiteRating(PortalChatter):
context = dict(request.context)
context['rating_include'] = True
request.context = context
return super(WebsiteRating, self).portal_message_fetch(res_model, res_id, domain=domain, limit=limit, offset=offset, **kw)
return super(PortalChatter, self).portal_message_fetch(res_model, res_id, domain=domain, limit=limit, offset=offset, **kw)
@@ -2,8 +2,6 @@ odoo.define('website_rating.thread', function (require) {
'use strict';
var core = require('web.core');
var publicWidget = require('web.public.widget');
var session = require('web.session');
var portalChatter = require('portal.chatter');
var utils = require('web.utils');
@@ -67,7 +65,10 @@ PortalComposer.include({
// rating stars
self.$input = self.$('input[name="rating_value"]');
self.$star_list = self.$('.stars').find('i');
self.set("star_value", self.options.default_rating_value); // set the default value to trigger the display of star widget
// set the default value to trigger the display of star widget and update the hidden input value.
self.set("star_value", self.options.default_rating_value);
self.$input.val(self.options.default_rating_value * STAR_RATING_RATIO);
});
},
@@ -136,7 +137,7 @@ PortalChatter.include({
}),
xmlDependencies: (PortalChatter.prototype.xmlDependencies || [])
.concat([
'/website_rating/static/src/xml/website_mail.xml',
'/website_rating/static/src/xml/portal_tools.xml',
'/website_rating/static/src/xml/portal_chatter.xml'
]),
@@ -291,64 +292,4 @@ PortalChatter.include({
this._changeCurrentPage(1, domain);
},
});
/**
* RatingPopupComposer
*
* Display the rating average with a static star widget, and open
* a popup with the portal composer when clicking on it.
**/
var RatingPopupComposer = publicWidget.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'] / STAR_RATING_RATIO * 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': options['disable_composer'] ? false : !session.is_website_user,
'display_rating': true,
'csrf_token': odoo.csrf_token,
'user_id': session.user_id,
});
},
/**
* @override
*/
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 Promise.all(defs);
},
});
publicWidget.registry.RatingPopupComposer = publicWidget.Widget.extend({
selector: '.o_rating_popup_composer',
/**
* @override
*/
start: function () {
var ratingPopup = new RatingPopupComposer(this, this.$el.data());
return Promise.all([
this._super.apply(this, arguments),
ratingPopup.appendTo(this.$el)
]);
},
});
});
@@ -0,0 +1,71 @@
odoo.define('portal.rating.composer', function (require) {
'use strict';
var publicWidget = require('web.public.widget');
var session = require('web.session');
var portalChatter = require('portal.chatter');
var PortalComposer = portalChatter.PortalComposer;
var STAR_RATING_RATIO = 2; // conversion factor from the star (1-5) to the db rating range (1-10)
/**
* RatingPopupComposer
*
* Display the rating average with a static star widget, and open
* a popup with the portal composer when clicking on it.
**/
var RatingPopupComposer = publicWidget.Widget.extend({
template: 'website_rating.PopupComposer',
xmlDependencies: [
'/portal/static/src/xml/portal_chatter.xml',
'/website_rating/static/src/xml/portal_tools.xml',
'/website_rating/static/src/xml/portal_rating_composer.xml',
],
init: function (parent, options) {
this._super.apply(this, arguments);
this.rating_avg = Math.round(options['ratingAvg'] / STAR_RATING_RATIO * 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': options['disable_composer'] ? false : !session.is_website_user,
'display_rating': true,
'csrf_token': odoo.csrf_token,
'user_id': session.user_id,
});
},
/**
* @override
*/
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 Promise.all(defs);
},
});
publicWidget.registry.RatingPopupComposer = publicWidget.Widget.extend({
selector: '.o_rating_popup_composer',
/**
* @override
*/
start: function () {
var ratingPopup = new RatingPopupComposer(this, this.$el.data());
return Promise.all([
this._super.apply(this, arguments),
ratingPopup.appendTo(this.$el)
]);
},
});
});
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<!--
Inherited templates from portal to custom chatter with rating
-->
@@ -37,57 +36,4 @@
</t>
</t>
</t>
<!--
Popup Rating Composer Widget
It can alse be used to modify a message
-->
<t t-name="website_rating.PopupComposer">
<div class="d-flex flex-wrap align-items-center">
<div class="text-nowrap">
<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">
<small>(<t t-esc="widget.rating_total"/> ratings)</small>
</t>
</div>
<button t-if="widget.options['display_composer']" type="button" class="btn btn-sm btn-primary mx-3" data-toggle="modal" data-target="#ratingpopupcomposer">
<t t-if="widget.options['display_composer']">
<t t-if="widget.options['default_message_id']">
Modify your review
</t>
<t t-else="">
Add a review
</t>
</t>
</button>
</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 o_rating_popup_composer_label" id="ratingpopupcomposerlabel">
<t t-if="widget.options['default_message_id']">
Modify your review
</t>
<t t-else="">
Add a review
</t>
</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span>&amp;times;</span>
</button>
</div>
<div class="modal-body">
<div class="o_portal_chatter_composer"/>
</div>
</div>
</div>
</div>
</t>
</templates>
@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<!--
Popup Rating Composer Widget
It can alse be used to modify a message
-->
<t t-name="website_rating.PopupComposer">
<div class="d-flex flex-wrap align-items-center">
<div class="text-nowrap">
<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">
<small>(<t t-esc="widget.rating_total"/> ratings)</small>
</t>
</div>
<button t-if="widget.options['display_composer']" type="button" class="btn btn-sm btn-primary mx-3" data-toggle="modal" data-target="#ratingpopupcomposer">
<t t-if="widget.options['display_composer']">
<t t-if="widget.options['default_message_id']">
Modify your review
</t>
<t t-else="">
Add a review
</t>
</t>
</button>
</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 o_rating_popup_composer_label" id="ratingpopupcomposerlabel">
<t t-if="widget.options['default_message_id']">
Modify your review
</t>
<t t-else="">
Add a review
</t>
</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span>&amp;times;</span>
</button>
</div>
<div class="modal-body">
<div class="o_portal_chatter_composer"/>
</div>
</div>
</div>
</div>
</t>
</templates>
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="website_rating.rating_stars_static">
<t t-set="val_integer" t-value="Math.floor(val)"/>
<t t-set="val_decimal" t-value="val - val_integer"/>
@@ -85,5 +84,4 @@
<input type="hidden" readonly="readonly" name="rating_value" t-att-value="default_rating || ''"/>
</div>
</t>
</templates>
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="assets_frontend" inherit_id="web_editor.assets_frontend" name="Portal Rating Assets">
<xpath expr="//link[last()]" position="after">
<link rel="stylesheet" type="text/scss" href="/website_rating/static/src/scss/website_rating.scss"/>
</xpath>
<xpath expr="//script[last()]" position="after">
<script type="text/javascript" src="/website_rating/static/src/js/portal_chatter.js"></script>
<script type="text/javascript" src="/website_rating/static/src/js/portal_rating_composer.js"></script>
</xpath>
</template>
</odoo>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="message_thread" inherit_id="portal.message_thread">
<xpath expr="//div[@id='discussion']" position="attributes">
<attribute name="t-att-data-display_rating">display_rating or False</attribute>
</xpath>
</template>
</odoo>
@@ -1,43 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="assets_frontend" inherit_id="website.assets_frontend" name="Website rating frontend assets">
<xpath expr="." position="inside">
<script type="text/javascript" src="/website_rating/static/src/js/website_mail.js"></script>
<link rel="stylesheet" type="text/scss" href="/website_rating/static/src/scss/website_rating.scss"/>
</xpath>
</template>
<template id="message_thread" inherit_id="portal.message_thread">
<xpath expr="//div[@id='discussion']" position="attributes">
<attribute name="t-att-data-display_rating">display_rating or False</attribute>
</xpath>
</template>
<!--
Rating widget static: show 5 stars (full or empty) regarding the given rating_avg and rating_count
-->
<template id="rating_widget_stars_static" name="Rating: static star widget">
<t t-set="rating_avg" t-value="round(rating_avg * 100) / 100 / 2"/>
<t t-set="val_decimal" t-value="round(rating_avg % 1, 1)"/>
<t t-set="val_integer" t-value="int(rating_avg)"/>
<t t-set="empty_star" t-value="5 - (val_integer+1) if val_decimal else 5 - val_integer"/>
<div class="o_website_rating_static" t-att-style="'display:inline' if inline_mode else ''" t-att-title="rating_avg">
<t t-foreach="range(0, val_integer)" t-as="num">
<i class="fa fa-star" role="img"></i>
</t>
<t t-if="val_decimal">
<i class="fa fa-star-half-o" role="img"></i>
</t>
<t t-foreach="range(0, empty_star)" t-as="num">
<i class="fa fa-star text-black-25" role="img"></i>
</t>
<t t-if="rating_count">
(<t t-esc="rating_count"/>)
</t>
</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.
@@ -10,8 +10,8 @@ var QWeb = core.qweb;
var FieldFloatRating = basicFields.FieldFloat.extend({
xmlDependencies: !basicFields.FieldFloat.prototype.xmlDependencies ?
['/website_rating/static/src/xml/website_mail.xml'] : basicFields.FieldFloat.prototype.xmlDependencies.concat(
['/website_rating/static/src/xml/website_mail.xml']
['/website_rating/static/src/xml/portal_tools.xml'] : basicFields.FieldFloat.prototype.xmlDependencies.concat(
['/website_rating/static/src/xml/portal_tools.xml']
),
description: "",
//--------------------------------------------------------------------------