[IMP] portal[_rating],website_slides: improve star filtering interface

The implementation seemed buggy as you had to click twice on a rating to
activate the filter; this fixes the problem.

It also improves a bit the interface:
- by allowing to click on another rating directly without having to deactivate
first the current filter
- by replacing "Remove Selection" by a red fa-times
- by adding a spinner on the messages zone while the messages are loading when
the connection is slow (the spinner appears only after half a second if the
server doesn't response in the meantime)
- by setting some minimal heights to avoid seeing the footer moving when
switching from course to review and when changing the star filter (which change
the number of message displayed)

Technical notes:
The double click problem was caused by an update of the view when the rating
filter is changed. When re-clicking on the same rating the view was not
re-rendered and the change (selection) in the view were kept.

To solve that problem we have implemented the selection directly in the view
and the css. As it doesn't rely anymore on changes performed in javascript
in the dom, the re-render of the view after fetching the data from the server
reflect the selection done by the user.

Task-2754954

closes odoo/odoo#85757

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Pierre-Yves Dufays
2022-03-25 11:22:45 +01:00
parent 8bae2f6227
commit f89fce4501
6 changed files with 78 additions and 53 deletions
@@ -278,7 +278,7 @@ var PortalChatter = publicWidget.Widget.extend({
_onChangeDomain: function () {
var self = this;
this.messageFetch().then(function () {
return this.messageFetch().then(function () {
var p = self._currentPage;
self.set('pager', self._pager(p));
});
@@ -18,8 +18,8 @@ var qweb = core.qweb;
PortalChatter.include({
events: _.extend({}, PortalChatter.prototype.events, {
// star based control
'click .o_website_rating_select': '_onClickStarDomain',
'click .o_website_rating_select_text': '_onClickStarDomainReset',
'click .o_website_rating_table_row': '_onClickStarDomain',
'click .o_website_rating_selection_reset': '_onClickStarDomainReset',
// publisher comments
'click .o_wrating_js_publisher_comment_btn': '_onClickPublisherComment',
'click .o_wrating_js_publisher_comment_edit': '_onClickPublisherComment',
@@ -235,6 +235,25 @@ PortalChatter.include({
// Handlers
//--------------------------------------------------------------------------
/**
* Show a spinner and hide messages during loading.
*
* @override
* @returns {Promise}
*/
_onChangeDomain: function () {
const spinnerDelayed = setTimeout(()=> {
this.$('.o_portal_chatter_messages_loading').removeClass('d-none');
this.$('.o_portal_chatter_messages').addClass('d-none');
}, 500);
return this._super.apply(this, arguments).finally(()=>{
clearTimeout(spinnerDelayed);
// Hide spinner and show messages
this.$('.o_portal_chatter_messages_loading').addClass('d-none');
this.$('.o_portal_chatter_messages').removeClass('d-none');
});
},
/**
* @private
* @param {MouseEvent} ev
@@ -242,19 +261,7 @@ PortalChatter.include({
_onClickStarDomain: function (ev) {
var $tr = this.$(ev.currentTarget);
var num = $tr.data('star');
if ($tr.css('opacity') === '1') {
this.set('rating_value', num);
this.$('.o_website_rating_select').css({
'opacity': 0.5,
});
this.$('.o_website_rating_select_text[data-star="' + num + '"]').css({
'visibility': 'visible',
'opacity': 1,
});
this.$('.o_website_rating_select[data-star="' + num + '"]').css({
'opacity': 1,
});
}
this.set('rating_value', num);
},
/**
* @private
@@ -264,10 +271,6 @@ PortalChatter.include({
ev.stopPropagation();
ev.preventDefault();
this.set('rating_value', false);
this.$('.o_website_rating_select_text').css('visibility', 'hidden');
this.$('.o_website_rating_select').css({
'opacity': 1,
});
},
/**
@@ -11,7 +11,7 @@ $o-w-rating-star-color: #FACC2E;
}
/* progress bars */
table.o_website_rating_progress_table {
table.o_website_rating_table {
width: 100%;
overflow: visible;
@@ -19,13 +19,10 @@ $o-w-rating-star-color: #FACC2E;
min-width: 50px;
white-space: nowrap;
}
.o_website_rating_select[style*="opacity: 1"] {
cursor: pointer;
}
.o_website_rating_table_progress{
min-width: 120px;
> .progress {
margin-bottom: 5px;
margin-bottom: 2px;
margin-left: 5px;
margin-right: 5px;
}
@@ -39,12 +36,14 @@ $o-w-rating-star-color: #FACC2E;
font-size: $font-size-sm;
}
.o_website_rating_table_reset {
.o_website_rating_select_text {
visibility: hidden;
.o_website_rating_selection_reset {
color: $red;
}
}
.o_website_rating_table_row:not(o_website_rating_table_row_selected) {
cursor: pointer;
}
}
}
/* Star Widget */
@@ -86,3 +85,9 @@ $o-w-rating-star-color: #FACC2E;
.o_rating_popup_composer_label {
color: color-yiq(white);
}
.o_portal_rating_chatter_messages {
/* Goal of min-height: push the footer out of the screen (in most use-case) to avoid seeing it moving when switching
the star filter when there are few messages */
min-height: 40vh;
}
@@ -16,6 +16,9 @@
</t>
<t t-extend="portal.chatter_messages">
<t t-jquery="div[class='o_portal_chatter_messages']">
this.attr('class', this.attr("class") + ' o_portal_rating_chatter_messages');
</t>
<t t-jquery="t[t-out='message.body']" t-operation="before">
<t t-if="message['rating_value']">
<t t-call="portal_rating.rating_stars_static">
@@ -43,6 +46,15 @@
<t t-call="portal.chatter_message_count"/>
</t>
</t>
<t t-jquery="t[t-call='portal.chatter_messages']" t-operation="before">
<div class="o_portal_chatter_messages_loading d-none">
<div class="d-flex justify-content-center">
<div class="spinner-border text-primary" role="status">
<span class="sr-only">Loading...</span>
</div>
</div>
</div>
</t>
</t>
<!--
@@ -36,32 +36,33 @@
<div t-attf-class="#{two_columns and 'col-lg-12' or 'col-lg-6'}" t-if="!_.isEmpty(widget.get('rating_card_values'))">
<hr t-if="two_columns"/>
<p t-if="!two_columns"><strong>Details</strong></p>
<div class="o_website_rating_progress_bars">
<table class="o_website_rating_progress_table">
<t t-foreach="widget.get('rating_card_values')['percent']" t-as="percent">
<tr class="o_website_rating_select" t-att-data-star="percent['num']" style="opacity: 1">
<td class="o_website_rating_table_star_num text-nowrap" t-att-data-star="percent['num']">
<t t-esc="percent['num']"/> stars
</td>
<td class="o_website_rating_table_progress">
<div class="progress">
<div class="progress-bar o_rating_progressbar" role="progressbar" t-att-aria-valuenow="percent['percent']" aria-valuemin="0" aria-valuemax="100" t-att-style="'width:' + percent['percent'] + '%;'">
</div>
<t t-set="selected_rating" t-value="widget.get('rating_value')"/>
<table t-attf-class="o_website_rating_table #{selected_rating and 'o_website_rating_table_has_selection' or ''}">
<t t-foreach="widget.get('rating_card_values')['percent']" t-as="percent">
<t t-set="row_selected" t-value="percent['num'] == selected_rating"/>
<tr t-attf-class="o_website_rating_table_row #{row_selected ? 'o_website_rating_table_row_selected' : (selected_rating ? 'opacity-50' : '')}"
t-att-data-star="percent['num']">
<td class="o_website_rating_table_star_num text-nowrap" t-att-data-star="percent['num']">
<t t-esc="percent['num']"/> stars
</td>
<td class="o_website_rating_table_progress">
<div class="progress">
<div class="progress-bar o_rating_progressbar" role="progressbar" t-att-aria-valuenow="percent['percent']" aria-valuemin="0" aria-valuemax="100" t-att-style="'width:' + percent['percent'] + '%;'">
</div>
</td>
<td class="o_website_rating_table_percent">
<strong><t t-esc="Math.round(percent['percent'] * 100) / 100"/>%</strong>
</td>
<td class="o_website_rating_table_reset">
<button class="btn btn-link o_website_rating_select_text" t-att-data-star="percent['num']">
<i t-attf-class="fa fa-times d-block #{!two_columns and 'd-sm-none' or ''}" role="img" aria-label="Remove Selection"/>
<span t-attf-class="d-none #{!two_columns and 'd-sm-block' or ''}">Remove Selection</span>
</button>
</td>
</tr>
</t>
</table>
</div>
</div>
</td>
<td class="o_website_rating_table_percent">
<strong><t t-esc="Math.round(percent['percent'] * 100) / 100"/>%</strong>
</td>
<td class="o_website_rating_table_reset">
<button t-attf-class="btn btn-link o_website_rating_selection_reset #{row_selected and 'visible' or 'invisible'}"
t-att-data-star="percent['num']">
<i class="fa fa-times d-block" role="img" aria-label="Remove Selection"/>
</button>
</td>
</tr>
</t>
</table>
</div>
</div>
</t>
@@ -365,6 +365,10 @@ $truncate-limits: 2, 3, 10;
}
.o_wslides_course_main {
/* Goal of min-height: push the footer out of the screen (in most use-case) to avoid seeing it moving when switching
from course to review tab */
min-height: 70vh;
.o_wslides_nav_tabs {
@include media-breakpoint-up(md) {
@include o-wslides-tabs();