[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:
Jeremy Kersten
2021-08-27 18:46:15 +00:00
parent 03866fd2ce
commit ef531afe39
5 changed files with 68 additions and 16 deletions
+9 -1
View File
@@ -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"><!-- &emsp; -->
<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>