[IMP] website(_sale): allow to force numberOfRecord for dynamic snippet
Now you can specify into the dynamic_filter_template the number of record to use for desktop, mobile, and the number of record to fetch. Some template have only sense to be shown with 1 record e.g. a full width. Syntax: Add on root element one or more of these attributes: data-number-of-elements="2" -> number of record on Desktop data-number-of-elements-sm="2" -> number of record on Mobile data-number-of-elements-fetch="2" -> number of record to fetch closes odoo/odoo#75662 Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
This commit is contained in:
@@ -11,6 +11,7 @@ import werkzeug.utils
|
||||
import werkzeug.wrappers
|
||||
|
||||
from itertools import islice
|
||||
from lxml import etree
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import odoo
|
||||
@@ -330,7 +331,14 @@ class Website(Home):
|
||||
domain = [['key', 'ilike', '.dynamic_filter_template_'], ['type', '=', 'qweb']]
|
||||
if filter_name:
|
||||
domain.append(['key', 'ilike', escape_psql('_%s_' % filter_name)])
|
||||
templates = request.env['ir.ui.view'].sudo().search_read(domain, ['key', 'name'])
|
||||
templates = request.env['ir.ui.view'].sudo().search_read(domain, ['key', 'name', 'arch_db'])
|
||||
|
||||
for t in templates:
|
||||
children = etree.fromstring(t.pop('arch_db')).getchildren()
|
||||
attribs = children and children[0].attrib or {}
|
||||
t['numOfEl'] = attribs.get('data-number-of-elements')
|
||||
t['numOfElSm'] = attribs.get('data-number-of-elements-sm')
|
||||
t['numOfElFetch'] = attribs.get('data-number-of-elements-fetch')
|
||||
return templates
|
||||
|
||||
# ------------------------------------------------------
|
||||
|
||||
@@ -47,10 +47,28 @@ const dynamicSnippetOptions = options.Class.extend({
|
||||
}
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Public
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
async updateUIVisibility() {
|
||||
await this._super(...arguments);
|
||||
const template = this._getCurrentTemplate();
|
||||
const groupingMessage = this.el.querySelector('.o_grouping_message');
|
||||
groupingMessage.classList.toggle('d-none', !!template.numOfEl && !!template.numOfElSm);
|
||||
},
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Private
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
_getCurrentTemplate: function () {
|
||||
return this.dynamicFilterTemplates[this.$target.get(0).dataset['templateKey']];
|
||||
},
|
||||
|
||||
_getTemplateClass: function (templateKey) {
|
||||
return templateKey.replace(/.*\.dynamic_filter_template_/, "s_");
|
||||
},
|
||||
@@ -65,6 +83,19 @@ const dynamicSnippetOptions = options.Class.extend({
|
||||
// Hide if exaclty one is available: show when none to help understand what is missing
|
||||
return Object.keys(this.dynamicFilters).length !== 1;
|
||||
}
|
||||
|
||||
if (widgetName === 'number_of_elements_opt') {
|
||||
return !this._getCurrentTemplate().numOfEl;
|
||||
}
|
||||
|
||||
if (widgetName === 'number_of_elements_small_devices_opt') {
|
||||
return !this._getCurrentTemplate().numOfElSm;
|
||||
}
|
||||
|
||||
if (widgetName === 'number_of_records_opt') {
|
||||
return !this._getCurrentTemplate().numOfElFetch;
|
||||
}
|
||||
|
||||
return this._super.apply(this, arguments);
|
||||
},
|
||||
/**
|
||||
@@ -74,10 +105,10 @@ const dynamicSnippetOptions = options.Class.extend({
|
||||
*/
|
||||
_refreshPublicWidgets: function () {
|
||||
return this._super.apply(this, arguments).then(() => {
|
||||
const selectedTemplateId = this.$target.get(0).dataset['templateKey'];
|
||||
const template = this._getCurrentTemplate();
|
||||
this.$target.find('.missing_option_warning').toggleClass(
|
||||
'd-none',
|
||||
!!this.dynamicFilterTemplates[selectedTemplateId]
|
||||
!!template
|
||||
);
|
||||
});
|
||||
},
|
||||
@@ -219,6 +250,17 @@ const dynamicSnippetOptions = options.Class.extend({
|
||||
this.$target.removeClass(this._getTemplateClass(oldTemplate));
|
||||
}
|
||||
this.$target.addClass(this._getTemplateClass(newTemplate));
|
||||
|
||||
const template = this.dynamicFilterTemplates[newTemplate];
|
||||
if (template.numOfEl) {
|
||||
this.$target[0].dataset.numberOfElements = template.numOfEl;
|
||||
}
|
||||
if (template.numOfElSm) {
|
||||
this.$target[0].dataset.numberOfElementsSmallDevices = template.numOfElSm;
|
||||
}
|
||||
if (template.numOfElFetch) {
|
||||
this.$target[0].dataset.numberOfRecords = template.numOfElFetch;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Sets the option value.
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
<t t-name="website.s_dynamic_snippet.carousel">
|
||||
<div t-att-id="uniqueId" class="carousel slide" t-att-data-interval="interval">
|
||||
<!-- Content -->
|
||||
<t t-set="colClass" t-value="'d-flex flex-grow-0 flex-shrink-0 col-' + Math.trunc(12 / chunkSize).toString()"/>
|
||||
<t t-set="slideIndexGenerator" t-value="Array.from(Array(Math.ceil(data.length/chunkSize)).keys())"/>
|
||||
<t t-set="itemIndexGenerator" t-value="Array.from(Array(chunkSize).keys())"/>
|
||||
<div class="carousel-inner row w-100 mx-auto" role="listbox">
|
||||
<t t-set="colClass" t-value="'d-flex flex-grow-0 flex-shrink-0 col-' + Math.trunc(12 / chunkSize).toString()"/>
|
||||
<t t-set="slideIndexGenerator" t-value="Array.from(Array(Math.ceil(data.length/chunkSize)).keys())"/>
|
||||
<t t-set="itemIndexGenerator" t-value="Array.from(Array(chunkSize).keys())"/>
|
||||
<t t-foreach="slideIndexGenerator" t-as="slideIndex">
|
||||
<div t-attf-class="carousel-item #{slideIndex_first ? 'active' : ''}">
|
||||
<div class="row">
|
||||
@@ -22,14 +22,16 @@
|
||||
</t>
|
||||
</div>
|
||||
<!-- Controls -->
|
||||
<a t-attf-href="##{uniqueId}" class="carousel-control-prev" data-slide="prev" role="button" aria-label="Previous" title="Previous">
|
||||
<span class="fa fa-chevron-circle-left fa-2x"/>
|
||||
<span class="sr-only">Previous</span>
|
||||
</a>
|
||||
<a t-attf-href="##{uniqueId}" class="carousel-control-next" data-slide="next" role="button" aria-label="Next" title="Next">
|
||||
<span class="fa fa-chevron-circle-right fa-2x"/>
|
||||
<span class="sr-only">Next</span>
|
||||
</a>
|
||||
<t t-if='slideIndexGenerator.length > 1'>
|
||||
<a t-attf-href="##{uniqueId}" class="carousel-control-prev" data-slide="prev" role="button" aria-label="Previous" title="Previous">
|
||||
<span class="fa fa-chevron-circle-left fa-2x"/>
|
||||
<span class="sr-only">Previous</span>
|
||||
</a>
|
||||
<a t-attf-href="##{uniqueId}" class="carousel-control-next" data-slide="next" role="button" aria-label="Next" title="Next">
|
||||
<span class="fa fa-chevron-circle-right fa-2x"/>
|
||||
<span class="sr-only">Next</span>
|
||||
</a>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<we-select string="Fetched elements" data-name="number_of_records_opt" data-attribute-name="numberOfRecords" data-no-preview="true">
|
||||
<we-button t-foreach="range(1, 17)" t-as="value" t-att-data-select-data-attribute="value" t-esc="value"/>
|
||||
</we-select>
|
||||
<we-title class="mt-2"><t t-esc="grouping_message"/></we-title>
|
||||
<we-title class="mt-2 o_grouping_message"><t t-esc="grouping_message"/></we-title>
|
||||
<we-select string="⌙ Desktop" data-name="number_of_elements_opt" data-attribute-name="numberOfElements" data-no-preview="true"><!--   -->
|
||||
<we-button data-select-data-attribute="1">1</we-button>
|
||||
<we-button data-select-data-attribute="2">2</we-button>
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
</template>
|
||||
|
||||
<template id="dynamic_filter_template_product_product_mini_image" name="Image only">
|
||||
<t t-foreach="records" t-as="data">
|
||||
<t t-foreach="records" t-as="data" data-number-of-elements="4" data-number-of-elements-sm="1" data-number-of-elements-fetch="8">
|
||||
<t t-set="record" t-value="data['_record']"/>
|
||||
<div class="card h-100" t-att-data-url="record.website_url">
|
||||
<div t-if="is_sample" class="h5 o_ribbon_right bg-primary text-uppercase">Sample</div>
|
||||
|
||||
Reference in New Issue
Block a user