diff --git a/pos_default_empty_image/README.rst b/pos_default_empty_image/README.rst new file mode 100644 index 00000000..494ecc69 --- /dev/null +++ b/pos_default_empty_image/README.rst @@ -0,0 +1,3 @@ +================================================ +Optimize loading time for products without image +================================================ diff --git a/pos_default_empty_image/__init__.py b/pos_default_empty_image/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/pos_default_empty_image/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/pos_default_empty_image/__manifest__.py b/pos_default_empty_image/__manifest__.py new file mode 100644 index 00000000..eb2ae81f --- /dev/null +++ b/pos_default_empty_image/__manifest__.py @@ -0,0 +1,21 @@ +# © 2015 Akretion, GRAP, OCA +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +{ + 'name': 'POS Default empty image', + 'version': '12.0.1.0.0', + 'category': 'Point Of Sale', + 'summary': 'Optimize loading time for products without image', + 'author': "Akretion, GRAP, Odoo Community Association (OCA)", + 'website': "https://www.github.com/OCA/pos", + 'license': 'AGPL-3', + 'depends': [ + 'point_of_sale', + ], + 'data': [ + 'views/templates.xml', + ], + 'qweb': [ + 'static/src/xml/pos_default_empty_image.xml', + ], + 'installable': True, +} diff --git a/pos_default_empty_image/i18n/pos_default_empty_image.pot b/pos_default_empty_image/i18n/pos_default_empty_image.pot new file mode 100644 index 00000000..8741b82e --- /dev/null +++ b/pos_default_empty_image/i18n/pos_default_empty_image.pot @@ -0,0 +1,25 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_default_empty_image +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 10.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: pos_default_empty_image +#: model:ir.model.fields,field_description:pos_default_empty_image.field_product_product_has_image +msgid "Has Image" +msgstr "" + +#. module: pos_default_empty_image +#: model:ir.model,name:pos_default_empty_image.model_product_product +msgid "Product" +msgstr "" + diff --git a/pos_default_empty_image/models/__init__.py b/pos_default_empty_image/models/__init__.py new file mode 100644 index 00000000..5c74c8c3 --- /dev/null +++ b/pos_default_empty_image/models/__init__.py @@ -0,0 +1 @@ +from . import product_product diff --git a/pos_default_empty_image/models/product_product.py b/pos_default_empty_image/models/product_product.py new file mode 100644 index 00000000..0cb6f822 --- /dev/null +++ b/pos_default_empty_image/models/product_product.py @@ -0,0 +1,20 @@ +# Copyright (C) 2017 - Today: +# GRAP (http://www.grap.coop) +# Akretion (http://www.akretion.com) +# @author: Sylvain LE GAL (https://twitter.com/legalsylvain) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import models, fields, api + + +class ProductProduct(models.Model): + _inherit = 'product.product' + + @api.multi + @api.depends('image') + def _compute_has_image(self): + for product in self: + product.has_image = product.image + + has_image = fields.Boolean( + compute='_compute_has_image', string='Has Image', store=True) diff --git a/pos_default_empty_image/readme/CONTRIBUTORS.rst b/pos_default_empty_image/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..d2ab100b --- /dev/null +++ b/pos_default_empty_image/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* Hparfr `Akretion `_ +* Sylvain LE GAL +* Invitu diff --git a/pos_default_empty_image/readme/DESCRIPTION.rst b/pos_default_empty_image/readme/DESCRIPTION.rst new file mode 100644 index 00000000..5b54d85a --- /dev/null +++ b/pos_default_empty_image/readme/DESCRIPTION.rst @@ -0,0 +1,47 @@ +This module extends the functionality of point of sale to make PoS load faster +and to improve products display. + +Point Of Sale Load faster +========================= + +In the point of sale, loading products without image spend unnecessary time +and resources. + +When you have 8000 products in your Point of Sale and most of them +don't have images, removing thousands of useless requests is welcome: +the PoS loads faster that way. + + +Improve products display +======================== + +By default, Odoo PoS display a useless generic image for products that doesn't +have images. + + .. figure:: ../static/description/pos_display_default.png + :width: 800 px + +With this module, the display of the product is changed, (Size of the name +is increased for better visibility); + + .. figure:: ../static/description/pos_display_improved.png + :width: 800 px + +Technical information +===================== + +Each time the PoS instantiate a product, it will add this code for each product + +.. code:: html + + + +The browser will trigger as many requests than there are different urls. + +If you have many products, the browser will soon reach his limit of +network connections to Odoo server and will wait for free slots instead of +loading other valuable contents. Then the PoS is then very slow to work with. + +This module adds a field has_image in product.product model. + +If product has no image, the product image url is not sent to the PoS diff --git a/pos_default_empty_image/readme/HISTORY.rst b/pos_default_empty_image/readme/HISTORY.rst new file mode 100644 index 00000000..ab2e9198 --- /dev/null +++ b/pos_default_empty_image/readme/HISTORY.rst @@ -0,0 +1,3 @@ +* Feb 2016 : First version +* March 2018 : migration to v10 and improvements for Display +* January 2020 : migration to v12 diff --git a/pos_default_empty_image/static/description/icon.png b/pos_default_empty_image/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/pos_default_empty_image/static/description/icon.png differ diff --git a/pos_default_empty_image/static/description/pos_display_default.png b/pos_default_empty_image/static/description/pos_display_default.png new file mode 100644 index 00000000..6974e40d Binary files /dev/null and b/pos_default_empty_image/static/description/pos_display_default.png differ diff --git a/pos_default_empty_image/static/description/pos_display_improved.png b/pos_default_empty_image/static/description/pos_display_improved.png new file mode 100644 index 00000000..0ec18e43 Binary files /dev/null and b/pos_default_empty_image/static/description/pos_display_improved.png differ diff --git a/pos_default_empty_image/static/src/css/pos_default_empty_image.css b/pos_default_empty_image/static/src/css/pos_default_empty_image.css new file mode 100644 index 00000000..5452eabf --- /dev/null +++ b/pos_default_empty_image/static/src/css/pos_default_empty_image.css @@ -0,0 +1,21 @@ +/* + Copyright (C) 2014 - Today: GRAP (http://www.grap.coop) + @author Julien WESTE + @author: Sylvain LE GAL (https://twitter.com/legalsylvain) + License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +*/ + +.product-img-without-image{ + height:25px !important; +} + +.product-name-without-image{ + bottom:auto !important; + top:25px !important; + padding-top:3px !important; + height:80px !important; + font-size: 24px !important; + line-height: 20px; + text-align: center; + word-wrap: break-word; +} diff --git a/pos_default_empty_image/static/src/js/models.js b/pos_default_empty_image/static/src/js/models.js new file mode 100644 index 00000000..344022b1 --- /dev/null +++ b/pos_default_empty_image/static/src/js/models.js @@ -0,0 +1,8 @@ +odoo.define('pos_default_empty_image.db', function (require) { + "use strict"; + + var models = require('point_of_sale.models'); + + // load new field 'has_image' for 'product.product' model + models.load_fields("product.product", ['has_image']); +}); diff --git a/pos_default_empty_image/static/src/js/widgets.js b/pos_default_empty_image/static/src/js/widgets.js new file mode 100644 index 00000000..1dc43d9f --- /dev/null +++ b/pos_default_empty_image/static/src/js/widgets.js @@ -0,0 +1,42 @@ +odoo.define('pos_default_empty_image.widgets', function (require) { + "use strict"; + + var screens = require('point_of_sale.screens'); + + var core = require('web.core'); + + var QWeb = core.qweb; + + //don't try to get an image if we know the product ain't one + var ProductListImageWidget = screens.ProductListWidget.include({ + get_product_image_url: function(product){ + if (product.has_image) + return this._super(product); + }, + + // Change product display if product has no image; + render_product: function(product){ + if (product.has_image){ + return this._super(product); + } + else { + var current_pricelist = this._get_active_pricelist(); + var cache_key = this.calculate_cache_key(product, current_pricelist); + var cached = this.product_cache.get_node(cache_key); + if(!cached){ + var product_html = QWeb.render('ProductNoImage',{ + widget: this, + product: product, + pricelist: current_pricelist, + }); + var product_node = document.createElement('div'); + product_node.innerHTML = product_html; + product_node = product_node.childNodes[1]; + this.product_cache.cache_node(cache_key,product_node); + return product_node; + } + return cached; + } + }, + }); +}); diff --git a/pos_default_empty_image/static/src/xml/pos_default_empty_image.xml b/pos_default_empty_image/static/src/xml/pos_default_empty_image.xml new file mode 100644 index 00000000..a76a07c5 --- /dev/null +++ b/pos_default_empty_image/static/src/xml/pos_default_empty_image.xml @@ -0,0 +1,22 @@ + + + +
+
+ + + + + + + + + + +
+
+ +
+
+
+
diff --git a/pos_default_empty_image/views/templates.xml b/pos_default_empty_image/views/templates.xml new file mode 100644 index 00000000..3cb6d9c4 --- /dev/null +++ b/pos_default_empty_image/views/templates.xml @@ -0,0 +1,12 @@ + + + +