From ef531afe39f9a586f4eac381651aa32eaec8b098 Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Thu, 26 Aug 2021 15:40:34 +0000 Subject: [PATCH] [IMP] website(_sale): allow to force numberOfRecord for dynamic snippet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- addons/website/controllers/main.py | 10 +++- .../src/snippets/s_dynamic_snippet/options.js | 46 ++++++++++++++++++- .../s_dynamic_snippet_carousel/000.xml | 24 +++++----- .../views/snippets/s_dynamic_snippet.xml | 2 +- .../data/product_snippet_template_data.xml | 2 +- 5 files changed, 68 insertions(+), 16 deletions(-) diff --git a/addons/website/controllers/main.py b/addons/website/controllers/main.py index 2411754bab0..55a76e6d4e7 100644 --- a/addons/website/controllers/main.py +++ b/addons/website/controllers/main.py @@ -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 # ------------------------------------------------------ diff --git a/addons/website/static/src/snippets/s_dynamic_snippet/options.js b/addons/website/static/src/snippets/s_dynamic_snippet/options.js index 3b6801f66c8..d34d756b0bd 100644 --- a/addons/website/static/src/snippets/s_dynamic_snippet/options.js +++ b/addons/website/static/src/snippets/s_dynamic_snippet/options.js @@ -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. diff --git a/addons/website/static/src/snippets/s_dynamic_snippet_carousel/000.xml b/addons/website/static/src/snippets/s_dynamic_snippet_carousel/000.xml index 075aebf97f3..d1c30ca51c2 100644 --- a/addons/website/static/src/snippets/s_dynamic_snippet_carousel/000.xml +++ b/addons/website/static/src/snippets/s_dynamic_snippet_carousel/000.xml @@ -3,10 +3,10 @@