diff --git a/addons/website_sale/__manifest__.py b/addons/website_sale/__manifest__.py index 271cc58515e..9120ca6d765 100644 --- a/addons/website_sale/__manifest__.py +++ b/addons/website_sale/__manifest__.py @@ -21,6 +21,7 @@ 'views/crm_team_views.xml', 'views/templates.xml', 'views/snippets.xml', + 'views/snippets/s_products_searchbar.xml', 'views/res_config_settings_views.xml', 'views/digest_views.xml', 'views/website_sale_visitor_views.xml', diff --git a/addons/website_sale/static/src/js/website_sale.editor.js b/addons/website_sale/static/src/js/website_sale.editor.js index 7e52f53dc04..e9188bbad7d 100644 --- a/addons/website_sale/static/src/js/website_sale.editor.js +++ b/addons/website_sale/static/src/js/website_sale.editor.js @@ -52,14 +52,9 @@ WebsiteNewMenu.include({ odoo.define('website_sale.editor', function (require) { 'use strict'; -var core = require('web.core'); -var Dialog = require('web.Dialog'); var options = require('web_editor.snippets.options'); var publicWidget = require('web.public.widget'); -var _t = core._t; -var qweb = core.qweb; - publicWidget.registry.websiteSaleCurrency = publicWidget.Widget.extend({ selector: '.oe_website_sale', disabledInEditableMode: false, @@ -88,7 +83,6 @@ function reload() { } options.registry.WebsiteSaleGridLayout = options.Class.extend({ - xmlDependencies: ['/website_sale/static/src/xml/website_sale.editor.xml'], /** * @override @@ -322,64 +316,4 @@ options.registry.WebsiteSaleProductsItem = options.Class.extend({ }).then(reload); }, }); - -/** - * Handles the edition of products search bar snippet. - */ -options.registry.ProductsSearchBar = options.Class.extend({ - xmlDependencies: ['/website_sale/static/src/xml/website_sale.editor.xml'], - - /** - * @override - */ - start: function () { - this.$searchProductsInput = this.$('.search-query'); - this.$searchOrderField = this.$('.o_wsale_search_order_by'); - return this._super.apply(this, arguments); - }, - - //-------------------------------------------------------------------------- - // Options - //-------------------------------------------------------------------------- - - /** - * @see this.selectClass for parameters - */ - openSearchbarSettings: function (previewMode, widgetValue, params) { - var self = this; - new Dialog(this, { - title: _t("Products Search Bar"), - $content: $(qweb.render('website_sale.dialog.productsSearchBar', { - currentOrderBy: this.$searchOrderField.val(), - currentLimit: parseInt(this.$searchProductsInput.attr('data-limit')), - currentDisplayDescription: this.$searchProductsInput.attr('data-display-description') === 'true', - currentDisplayPrice: this.$searchProductsInput.attr('data-display-price') === 'true', - currentDisplayImage: this.$searchProductsInput.attr('data-display-image') === 'true', - })), - buttons: [ - { - text: _t("Save"), - classes: 'btn-primary', - click: function () { - self.$searchOrderField.attr({ - 'value': this.$('#order_by').val(), - }); - self.$searchProductsInput.attr({ - 'data-limit': this.$('#use_autocomplete').is(':checked') ? this.$('#limit').val() : 0, - 'data-display-description': this.$('#display_description').is(':checked'), - 'data-display-price': this.$('#display_price').is(':checked'), - 'data-display-image': this.$('#display_image').is(':checked'), - }); - self.$target.trigger('content_changed'); - this.close(); - }, - }, - { - text: _t("Discard"), - close: true, - }, - ], - }).open(); - }, -}); }); diff --git a/addons/website_sale/static/src/js/website_sale.js b/addons/website_sale/static/src/js/website_sale.js index 9c5941a17db..f70a11992c1 100644 --- a/addons/website_sale/static/src/js/website_sale.js +++ b/addons/website_sale/static/src/js/website_sale.js @@ -147,13 +147,11 @@ odoo.define('website_sale.website_sale', function (require) { var core = require('web.core'); var config = require('web.config'); -var concurrency = require('web.concurrency'); var publicWidget = require('web.public.widget'); var VariantMixin = require('sale.VariantMixin'); var wSaleUtils = require('website_sale.utils'); require("web.zoomodoo"); -var qweb = core.qweb; publicWidget.registry.WebsiteSale = publicWidget.Widget.extend(VariantMixin, { selector: '.oe_website_sale', @@ -807,132 +805,4 @@ publicWidget.registry.websiteSaleCart = publicWidget.Widget.extend({ $(ev.currentTarget).closest('tr').find('.js_quantity').val(0).trigger('change'); }, }); - -/** - * @todo maybe the custom autocomplete logic could be extract to be reusable - */ -publicWidget.registry.productsSearchBar = publicWidget.Widget.extend({ - selector: '.o_wsale_products_searchbar_form', - xmlDependencies: ['/website_sale/static/src/xml/website_sale_utils.xml'], - events: { - 'input .search-query': '_onInput', - 'focusout': '_onFocusOut', - 'keydown .search-query': '_onKeydown', - }, - autocompleteMinWidth: 300, - - /** - * @constructor - */ - init: function () { - this._super.apply(this, arguments); - - this._dp = new concurrency.DropPrevious(); - - this._onInput = _.debounce(this._onInput, 400); - this._onFocusOut = _.debounce(this._onFocusOut, 100); - }, - /** - * @override - */ - start: function () { - this.$input = this.$('.search-query'); - - this.order = this.$('.o_wsale_search_order_by').val(); - this.limit = parseInt(this.$input.data('limit')); - this.displayDescription = !!this.$input.data('displayDescription'); - this.displayPrice = !!this.$input.data('displayPrice'); - this.displayImage = !!this.$input.data('displayImage'); - - if (this.limit) { - this.$input.attr('autocomplete', 'off'); - } - - return this._super.apply(this, arguments); - }, - - //-------------------------------------------------------------------------- - // Private - //-------------------------------------------------------------------------- - - /** - * @private - */ - _fetch: function () { - return this._rpc({ - route: '/shop/products/autocomplete', - params: { - 'term': this.$input.val(), - 'options': { - 'order': this.order, - 'limit': this.limit, - 'display_description': this.displayDescription, - 'display_price': this.displayPrice, - 'max_nb_chars': Math.round(Math.max(this.autocompleteMinWidth, parseInt(this.$el.width())) * 0.22), - }, - }, - }); - }, - /** - * @private - */ - _render: function (res) { - var $prevMenu = this.$menu; - this.$el.toggleClass('dropdown show', !!res); - if (res) { - var products = res['products']; - this.$menu = $(qweb.render('website_sale.productsSearchBar.autocomplete', { - products: products, - hasMoreProducts: products.length < res['products_count'], - currency: res['currency'], - widget: this, - })); - this.$menu.css('min-width', this.autocompleteMinWidth); - this.$el.append(this.$menu); - } - if ($prevMenu) { - $prevMenu.remove(); - } - }, - - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- - - /** - * @private - */ - _onInput: function () { - if (!this.limit) { - return; - } - this._dp.add(this._fetch()).then(this._render.bind(this)); - }, - /** - * @private - */ - _onFocusOut: function () { - if (!this.$el.has(document.activeElement).length) { - this._render(); - } - }, - /** - * @private - */ - _onKeydown: function (ev) { - switch (ev.which) { - case $.ui.keyCode.ESCAPE: - this._render(); - break; - case $.ui.keyCode.UP: - ev.preventDefault(); - this.$menu.children().last().focus(); - break; - case $.ui.keyCode.DOWN: - ev.preventDefault(); - this.$menu.children().first().focus(); - break; - } - }, -}); }); diff --git a/addons/website_sale/static/src/snippets/s_products_searchbar/000.js b/addons/website_sale/static/src/snippets/s_products_searchbar/000.js new file mode 100644 index 00000000000..5117d405a05 --- /dev/null +++ b/addons/website_sale/static/src/snippets/s_products_searchbar/000.js @@ -0,0 +1,136 @@ +odoo.define('website_sale.s_products_searchbar', function (require) { +'use strict'; + +const concurrency = require('web.concurrency'); +const publicWidget = require('web.public.widget'); + +const { qweb } = require('web.core'); + +/** + * @todo maybe the custom autocomplete logic could be extract to be reusable + */ +publicWidget.registry.productsSearchBar = publicWidget.Widget.extend({ + selector: '.o_wsale_products_searchbar_form', + xmlDependencies: ['/website_sale/static/src/xml/website_sale_utils.xml'], + events: { + 'input .search-query': '_onInput', + 'focusout': '_onFocusOut', + 'keydown .search-query': '_onKeydown', + }, + autocompleteMinWidth: 300, + + /** + * @constructor + */ + init: function () { + this._super.apply(this, arguments); + + this._dp = new concurrency.DropPrevious(); + + this._onInput = _.debounce(this._onInput, 400); + this._onFocusOut = _.debounce(this._onFocusOut, 100); + }, + /** + * @override + */ + start: function () { + this.$input = this.$('.search-query'); + + this.order = this.$('.o_wsale_search_order_by').val(); + this.limit = parseInt(this.$input.data('limit')); + this.displayDescription = !!this.$input.data('displayDescription'); + this.displayPrice = !!this.$input.data('displayPrice'); + this.displayImage = !!this.$input.data('displayImage'); + + if (this.limit) { + this.$input.attr('autocomplete', 'off'); + } + + return this._super.apply(this, arguments); + }, + + //-------------------------------------------------------------------------- + // Private + //-------------------------------------------------------------------------- + + /** + * @private + */ + _fetch: function () { + return this._rpc({ + route: '/shop/products/autocomplete', + params: { + 'term': this.$input.val(), + 'options': { + 'order': this.order, + 'limit': this.limit, + 'display_description': this.displayDescription, + 'display_price': this.displayPrice, + 'max_nb_chars': Math.round(Math.max(this.autocompleteMinWidth, parseInt(this.$el.width())) * 0.22), + }, + }, + }); + }, + /** + * @private + */ + _render: function (res) { + var $prevMenu = this.$menu; + this.$el.toggleClass('dropdown show', !!res); + if (res) { + var products = res['products']; + this.$menu = $(qweb.render('website_sale.productsSearchBar.autocomplete', { + products: products, + hasMoreProducts: products.length < res['products_count'], + currency: res['currency'], + widget: this, + })); + this.$menu.css('min-width', this.autocompleteMinWidth); + this.$el.append(this.$menu); + } + if ($prevMenu) { + $prevMenu.remove(); + } + }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * @private + */ + _onInput: function () { + if (!this.limit) { + return; + } + this._dp.add(this._fetch()).then(this._render.bind(this)); + }, + /** + * @private + */ + _onFocusOut: function () { + if (!this.$el.has(document.activeElement).length) { + this._render(); + } + }, + /** + * @private + */ + _onKeydown: function (ev) { + switch (ev.which) { + case $.ui.keyCode.ESCAPE: + this._render(); + break; + case $.ui.keyCode.UP: + ev.preventDefault(); + this.$menu.children().last().focus(); + break; + case $.ui.keyCode.DOWN: + ev.preventDefault(); + this.$menu.children().first().focus(); + break; + } + }, +}); +}); diff --git a/addons/website_sale/static/src/snippets/s_products_searchbar/options.js b/addons/website_sale/static/src/snippets/s_products_searchbar/options.js new file mode 100644 index 00000000000..d4fa9c1e835 --- /dev/null +++ b/addons/website_sale/static/src/snippets/s_products_searchbar/options.js @@ -0,0 +1,65 @@ +odoo.define('website_sale.s_products_searchbar_options', function (require) { +'use strict'; + +const Dialog = require('web.Dialog'); +const options = require('web_editor.snippets.options'); + +const { qweb, _t } = require('web.core'); + +options.registry.ProductsSearchBar = options.Class.extend({ + xmlDependencies: ['/website_sale/static/src/xml/website_sale.editor.xml'], + + /** + * @override + */ + start: function () { + this.$searchProductsInput = this.$('.search-query'); + this.$searchOrderField = this.$('.o_wsale_search_order_by'); + return this._super.apply(this, arguments); + }, + + //-------------------------------------------------------------------------- + // Options + //-------------------------------------------------------------------------- + + /** + * @see this.selectClass for parameters + */ + openSearchbarSettings: function (previewMode, widgetValue, params) { + var self = this; + new Dialog(this, { + title: _t("Products Search Bar"), + $content: $(qweb.render('website_sale.dialog.productsSearchBar', { + currentOrderBy: this.$searchOrderField.val(), + currentLimit: parseInt(this.$searchProductsInput.attr('data-limit')), + currentDisplayDescription: this.$searchProductsInput.attr('data-display-description') === 'true', + currentDisplayPrice: this.$searchProductsInput.attr('data-display-price') === 'true', + currentDisplayImage: this.$searchProductsInput.attr('data-display-image') === 'true', + })), + buttons: [ + { + text: _t("Save"), + classes: 'btn-primary', + click: function () { + self.$searchOrderField.attr({ + 'value': this.$('#order_by').val(), + }); + self.$searchProductsInput.attr({ + 'data-limit': this.$('#use_autocomplete').is(':checked') ? this.$('#limit').val() : 0, + 'data-display-description': this.$('#display_description').is(':checked'), + 'data-display-price': this.$('#display_price').is(':checked'), + 'data-display-image': this.$('#display_image').is(':checked'), + }); + self.$target.trigger('content_changed'); + this.close(); + }, + }, + { + text: _t("Discard"), + close: true, + }, + ], + }).open(); + }, +}); +}); diff --git a/addons/website_sale/views/snippets.xml b/addons/website_sale/views/snippets.xml index 3f8e62acfea..41810ec0ff2 100644 --- a/addons/website_sale/views/snippets.xml +++ b/addons/website_sale/views/snippets.xml @@ -1,29 +1,6 @@ - - - - - - - - - - - - - Search for a product - We have amazing products in our shop, check them now ! - - - - - - - - - @@ -96,13 +73,7 @@ Push to bottom - - - Products Search Bar - - , .s_wsale_products_searchbar_input diff --git a/addons/website_sale/views/snippets/s_products_searchbar.xml b/addons/website_sale/views/snippets/s_products_searchbar.xml new file mode 100644 index 00000000000..7658abe64dc --- /dev/null +++ b/addons/website_sale/views/snippets/s_products_searchbar.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + Search for a product + We have amazing products in our shop, check them now ! + + + + + + + + + + + + + Products Search Bar + + + , .s_wsale_products_searchbar_input + + + + + + + + + diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml index 230471ba92c..b7ae763cb57 100644 --- a/addons/website_sale/views/templates.xml +++ b/addons/website_sale/views/templates.xml @@ -47,6 +47,7 @@ +
We have amazing products in our shop, check them now !