[IMP] website: review snippet rating
Adding more control on the rating snippet. Choose the color, select other icons in media dialog, no limit to add active or inactive icons, display the rating inline or below the title. task-2146209 closes odoo/odoo#41169 Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
|
||||
.s_rating {
|
||||
.s_rating:not([data-vcss]) {
|
||||
$star: "\f005";
|
||||
$star-o: "\f006";
|
||||
$circle: "\f111";
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
.s_rating[data-vcss="001"] {
|
||||
&.s_rating_inline {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.s_rating_title {
|
||||
margin: 0;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
.s_rating_icons {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
odoo.define('website.s_rating_options', function (require) {
|
||||
'use strict';
|
||||
|
||||
const weWidgets = require('wysiwyg.widgets');
|
||||
const options = require('web_editor.snippets.options');
|
||||
|
||||
options.registry.Rating = options.Class.extend({
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
start: function () {
|
||||
this.iconType = this.$target[0].dataset.icon;
|
||||
this.faClassActiveCustomIcons = this.$target[0].dataset.activeCustomIcon || '';
|
||||
this.faClassInactiveCustomIcons = this.$target[0].dataset.inactiveCustomIcon || '';
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Options
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Displays the selected icon type.
|
||||
*
|
||||
* @see this.selectClass for parameters
|
||||
*/
|
||||
setIcons: function (previewMode, widgetValue, params) {
|
||||
this.iconType = widgetValue;
|
||||
this._renderIcons();
|
||||
this.$target[0].dataset.icon = widgetValue;
|
||||
delete this.$target[0].dataset.activeCustomIcon;
|
||||
delete this.$target[0].dataset.inactiveCustomIcon;
|
||||
},
|
||||
/**
|
||||
* Allows to select a font awesome icon with media dialog.
|
||||
*
|
||||
* @see this.selectClass for parameters
|
||||
*/
|
||||
customIcon: async function (previewMode, widgetValue, params) {
|
||||
return new Promise(resolve => {
|
||||
const dialog = new weWidgets.MediaDialog(
|
||||
this,
|
||||
{noImages: true, noDocuments: true, noVideos: true, mediaWidth: 1920},
|
||||
$('<i/>')
|
||||
);
|
||||
this._saving = false;
|
||||
dialog.on('save', this, function (attachments) {
|
||||
this._saving = true;
|
||||
const customClass = 'fa fa-fw ' + attachments.className;
|
||||
const $activeIcons = this.$target.find('.s_rating_active_icons > i');
|
||||
const $inactiveIcons = this.$target.find('.s_rating_inactive_icons > i');
|
||||
const $icons = params.customActiveIcon === 'true' ? $activeIcons : $inactiveIcons;
|
||||
$icons.removeClass().addClass(customClass);
|
||||
this.faClassActiveCustomIcons = $activeIcons.length > 0 ? $activeIcons.attr('class') : customClass;
|
||||
this.faClassInactiveCustomIcons = $inactiveIcons.length > 0 ? $inactiveIcons.attr('class') : customClass;
|
||||
this.$target[0].dataset.activeCustomIcon = this.faClassActiveCustomIcons;
|
||||
this.$target[0].dataset.inactiveCustomIcon = this.faClassInactiveCustomIcons;
|
||||
this.$target[0].dataset.icon = 'custom';
|
||||
this.iconType = 'custom';
|
||||
resolve();
|
||||
});
|
||||
dialog.on('closed', this, function () {
|
||||
if (!this._saving) {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
dialog.open();
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Sets the number of active icons.
|
||||
*
|
||||
* @see this.selectClass for parameters
|
||||
*/
|
||||
activeIconsNumber: function (previewMode, widgetValue, params) {
|
||||
this.nbActiveIcons = parseInt(widgetValue);
|
||||
this._createIcons();
|
||||
},
|
||||
/**
|
||||
* Sets the total number of icons.
|
||||
*
|
||||
* @see this.selectClass for parameters
|
||||
*/
|
||||
totalIconsNumber: function (previewMode, widgetValue, params) {
|
||||
this.nbTotalIcons = Math.max(parseInt(widgetValue), 1);
|
||||
this._createIcons();
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
_computeWidgetState: function (methodName, params) {
|
||||
switch (methodName) {
|
||||
case 'setIcons': {
|
||||
return this.$target[0].dataset.icon;
|
||||
}
|
||||
case 'activeIconsNumber': {
|
||||
this.nbActiveIcons = this.$target.find('.s_rating_active_icons > i').length;
|
||||
return this.nbActiveIcons;
|
||||
}
|
||||
case 'totalIconsNumber': {
|
||||
this.nbTotalIcons = this.$target.find('.s_rating_icons i').length;
|
||||
return this.nbTotalIcons;
|
||||
}
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
/**
|
||||
* Creates the icons.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_createIcons: function () {
|
||||
const $activeIcons = this.$target.find('.s_rating_active_icons');
|
||||
const $inactiveIcons = this.$target.find('.s_rating_inactive_icons');
|
||||
this.$target.find('.s_rating_icons i').remove();
|
||||
for (let i = 0; i < this.nbTotalIcons; i++) {
|
||||
if (i < this.nbActiveIcons) {
|
||||
$activeIcons.append('<i/> ');
|
||||
} else {
|
||||
$inactiveIcons.append('<i/> ');
|
||||
}
|
||||
}
|
||||
this._renderIcons();
|
||||
},
|
||||
/**
|
||||
* Renders icons with selected fonts.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_renderIcons: function () {
|
||||
const icons = {
|
||||
'fa-star': 'fa-star-o',
|
||||
'fa-thumbs-up': 'fa-thumbs-o-up',
|
||||
'fa-circle': 'fa-circle-o',
|
||||
'fa-square': 'fa-square-o',
|
||||
'fa-heart': 'fa-heart-o'
|
||||
};
|
||||
const faClassActiveIcons = (this.iconType === "custom") ? this.faClassActiveCustomIcons : 'fa fa-fw ' + this.iconType;
|
||||
const faClassInactiveIcons = (this.iconType === "custom") ? this.faClassInactiveCustomIcons : 'fa fa-fw ' + icons[this.iconType];
|
||||
const $activeIcons = this.$target.find('.s_rating_active_icons > i');
|
||||
const $inactiveIcons = this.$target.find('.s_rating_inactive_icons > i');
|
||||
$activeIcons.removeClass().addClass(faClassActiveIcons);
|
||||
$inactiveIcons.removeClass().addClass(faClassInactiveIcons);
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -114,6 +114,7 @@
|
||||
<script type="text/javascript" src="/website/static/src/snippets/s_popup/options.js"/>
|
||||
<script type="text/javascript" src="/website/static/src/snippets/s_product_catalog/options.js"/>
|
||||
<script type="text/javascript" src="/website/static/src/snippets/s_chart/options.js"/>
|
||||
<script type="text/javascript" src="/website/static/src/snippets/s_rating/options.js"/>
|
||||
|
||||
<script type="text/javascript" src="/website/static/src/js/editor/wysiwyg_multizone.js"/>
|
||||
<script type="text/javascript" src="/website/static/src/js/editor/wysiwyg_multizone_translate.js"/>
|
||||
|
||||
@@ -2,41 +2,60 @@
|
||||
<odoo>
|
||||
|
||||
<template id="s_rating" name="Rating">
|
||||
<div class="s_rating row">
|
||||
<div class="col-lg-12 s_rating_stars s_rating_3 s_rating_1x pt16 pb16">
|
||||
<h4>Quality</h4>
|
||||
<i class="fa fa-1x"/>
|
||||
<i class="fa fa-1x"/>
|
||||
<i class="fa fa-1x"/>
|
||||
<i class="fa fa-1x"/>
|
||||
<i class="fa fa-1x"/>
|
||||
<div class="s_rating_bar"/>
|
||||
<div class="s_rating pt16 pb16" data-vcss="001" data-icon="fa-star">
|
||||
<h4 class="s_rating_title">Quality</h4>
|
||||
<div class="s_rating_icons o_not_editable">
|
||||
<span class="s_rating_active_icons">
|
||||
<i class="fa fa-fw fa-star"/>
|
||||
<i class="fa fa-fw fa-star"/>
|
||||
<i class="fa fa-fw fa-star"/>
|
||||
</span>
|
||||
<span class="s_rating_inactive_icons">
|
||||
<i class="fa fa-fw fa-star-o"/>
|
||||
<i class="fa fa-fw fa-star-o"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="s_rating_options" inherit_id="website.snippet_options">
|
||||
<xpath expr="." position="inside">
|
||||
<div data-selector=".s_rating > div">
|
||||
<div data-js="Rating" data-selector=".s_rating">
|
||||
<we-select string="Icon">
|
||||
<we-button data-select-class="s_rating_stars"><i class="fa fa-fw fa-star"/> Stars</we-button>
|
||||
<we-button data-select-class="s_rating_squares"><i class="fa fa-fw fa-square"/> Squares</we-button>
|
||||
<we-button data-select-class="s_rating_hearts"><i class="fa fa-fw fa-heart"/> Hearts</we-button>
|
||||
<we-button data-select-class="s_rating_bar"><i class="fa fa-fw fa-tasks"/> Progress Bar</we-button>
|
||||
<we-button data-set-icons="fa-star"><i class="fa fa-fw fa-star"/> Stars</we-button>
|
||||
<we-button data-set-icons="fa-thumbs-up"><i class="fa fa-fw fa-thumbs-up"/> Thumbs</we-button>
|
||||
<we-button data-set-icons="fa-circle"><i class="fa fa-fw fa-circle"/> Circles</we-button>
|
||||
<we-button data-set-icons="fa-square"><i class="fa fa-fw fa-square"/> Squares</we-button>
|
||||
<we-button data-set-icons="fa-heart"><i class="fa fa-fw fa-heart"/> Hearts</we-button>
|
||||
<we-button data-set-icons="custom" class="d-none">Custom</we-button>
|
||||
</we-select>
|
||||
<we-select string="Value">
|
||||
<we-button data-select-class="">0</we-button>
|
||||
<we-button data-select-class="s_rating_1">1/5</we-button>
|
||||
<we-button data-select-class="s_rating_2">2/5</we-button>
|
||||
<we-button data-select-class="s_rating_3">3/5</we-button>
|
||||
<we-button data-select-class="s_rating_4">4/5</we-button>
|
||||
<we-button data-select-class="s_rating_5">5/5</we-button>
|
||||
</we-select>
|
||||
<we-select string="Size">
|
||||
<we-button data-select-class="s_rating_1x">Small</we-button>
|
||||
<we-button data-select-class="s_rating_2x">Medium</we-button>
|
||||
<we-button data-select-class="s_rating_3x">Big</we-button>
|
||||
<we-row string="Active Icon" class="o_we_inline">
|
||||
<we-colorpicker
|
||||
data-select-style=""
|
||||
data-apply-to=".s_rating_active_icons"
|
||||
data-css-property="color"
|
||||
data-color-prefix="text-"/>
|
||||
<we-button class="fa fa-fw fa-edit" data-custom-icon="true" data-custom-active-icon="true" data-no-preview="true"></we-button>
|
||||
</we-row>
|
||||
<we-row string="Inactive Icon" class="o_we_inline">
|
||||
<we-colorpicker
|
||||
data-select-style=""
|
||||
data-apply-to=".s_rating_inactive_icons"
|
||||
data-css-property="color"
|
||||
data-color-prefix="text-"/>
|
||||
<we-button class="fa fa-fw fa-edit" data-custom-icon="true" data-custom-active-icon="false" data-no-preview="true"></we-button>
|
||||
</we-row>
|
||||
<we-row string="Score" class="o_we_inline">
|
||||
<we-input data-active-icons-number="true" data-step="1"/>
|
||||
<span>/</span>
|
||||
<we-input data-total-icons-number="true" data-step="1"/>
|
||||
</we-row>
|
||||
<we-select string="Size" data-apply-to=".s_rating_icons">
|
||||
<we-button data-select-class="">Small</we-button>
|
||||
<we-button data-select-class="fa-2x">Medium</we-button>
|
||||
<we-button data-select-class="fa-3x">Big</we-button>
|
||||
</we-select>
|
||||
<we-checkbox string="Display Inline" data-select-class="s_rating_inline" data-no-preview="true"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</template>
|
||||
@@ -47,4 +66,10 @@
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
<template id="assets_snippet_s_rating_css_001" inherit_id="website.assets_frontend">
|
||||
<xpath expr="//link[last()]" position="after">
|
||||
<link rel="stylesheet" type="text/scss" href="/website/static/src/snippets/s_rating/001.scss"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -300,7 +300,7 @@
|
||||
</div>
|
||||
|
||||
<div data-js="sizing_y"
|
||||
data-selector="section, .row > div, .parallax, .s_hr, .s_btn, .carousel-item"
|
||||
data-selector="section, .row > div, .parallax, .s_hr, .s_btn, .carousel-item, .s_rating"
|
||||
data-exclude="section:has(> .carousel), .o_gallery .carousel-item"/>
|
||||
|
||||
<div data-js="sizing_x"
|
||||
|
||||
Reference in New Issue
Block a user