diff --git a/website_apps_store/README.rst b/website_apps_store/README.rst new file mode 100644 index 00000000..098b1107 --- /dev/null +++ b/website_apps_store/README.rst @@ -0,0 +1,86 @@ +================== +Website Apps Store +================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:e1a07ed3537367248ca005e8ca2a08b5077fa74bc33b4ea65005121eb6bf0bf9 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fapps--store-lightgray.png?logo=github + :target: https://github.com/OCA/apps-store/tree/18.0/website_apps_store + :alt: OCA/apps-store +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/apps-store-18-0/apps-store-18-0-website_apps_store + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/apps-store&target_branch=18.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Providing facility for displaying the module specific information in a +standard Odoo e-commerce website (front-end) and download the zip file +of the selected product. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +------- + +* BizzAppDev + +Contributors +------------ + +- Ruchir Shukla +- Eric Caudal +- Oscar Alcala +- `Tecnativa `__: + + - Víctor M.M. Torres + - Alexandre D. Díaz + - Ernesto Tejeda + +Maintainers +----------- + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +This module is part of the `OCA/apps-store `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/website_apps_store/__init__.py b/website_apps_store/__init__.py new file mode 100644 index 00000000..91c5580f --- /dev/null +++ b/website_apps_store/__init__.py @@ -0,0 +1,2 @@ +from . import controllers +from . import models diff --git a/website_apps_store/__manifest__.py b/website_apps_store/__manifest__.py new file mode 100644 index 00000000..e57ff84e --- /dev/null +++ b/website_apps_store/__manifest__.py @@ -0,0 +1,33 @@ +# Copyright 2018 BizzAppDev +# Copyright 2018-2021 Tecnativa +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). +{ + "name": "Website Apps Store", + "version": "18.0.1.0.0", + "author": "Odoo Community Association (OCA), BizzAppDev", + "website": "https://github.com/OCA/apps-store", + "license": "AGPL-3", + "category": "Sales", + "depends": [ + "website_sale", + "apps_download", + "apps_product_creator", + ], + "summary": "Website Apps Store", + "data": [ + "views/templates.xml", + "views/suspicious_templates.xml", + ], + "assets": { + "web.assets_frontend": [ + "website_apps_store/static/src/scss/main.scss", + "website_apps_store/static/src/js/website_sale.js", + ], + "web.assets_tests": [ + "website_apps_store/static/src/js/website_apps_store_tour.js", + ], + }, + "installable": True, + "auto_install": False, + "application": False, +} diff --git a/website_apps_store/controllers/__init__.py b/website_apps_store/controllers/__init__.py new file mode 100644 index 00000000..12a7e529 --- /dev/null +++ b/website_apps_store/controllers/__init__.py @@ -0,0 +1 @@ +from . import main diff --git a/website_apps_store/controllers/main.py b/website_apps_store/controllers/main.py new file mode 100644 index 00000000..df1f1470 --- /dev/null +++ b/website_apps_store/controllers/main.py @@ -0,0 +1,253 @@ +# Copyright 2017-2018 BizzAppDev +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import base64 +import logging + +from odoo import _, http +from odoo.exceptions import UserError, ValidationError +from odoo.http import request + +from odoo.addons.http_routing.models.ir_http import IrHttp +from odoo.addons.website.controllers.main import QueryURL +from odoo.addons.website_sale.controllers.main import TableCompute, WebsiteSale + +_logger = logging.getLogger(__name__) + +PPG = 20 # Products Per Page +PPR = 4 # Products Per Row + + +class WebsiteSaleCustom(WebsiteSale): + def _get_search_domain( + self, search, category, attrib_values, search_in_description=True + ): + domain = request.website.sale_product_domain() + if search: + for srch in search.split(" "): + domain += [ + "|", + "|", + "|", + "|", + "|", + "|", + "|", + "|", + ("name", "ilike", srch), + ("technical_name", "ilike", srch), + ("description", "ilike", srch), + ("description_sale", "ilike", srch), + ("product_variant_ids.default_code", "ilike", srch), + ( + "product_variant_ids.product_template_attribute_value_ids.name", + "ilike", + srch, + ), + ("product_variant_ids.app_description_rst_html", "ilike", srch), + ("product_variant_ids.app_author_ids.name", "ilike", srch), + ("product_variant_ids.app_summary", "ilike", srch), + ] + if category: + domain += [("public_categ_ids", "child_of", int(category))] + + if attrib_values: + attrib = None + ids = [] + for value in attrib_values: + if not attrib: + attrib = value[0] + ids.append(value[1]) + elif value[0] == attrib: + ids.append(value[1]) + else: + domain += [("attribute_line_ids.value_ids", "in", ids)] + attrib = value[0] + ids = [value[1]] + if attrib: + domain += [("attribute_line_ids.value_ids", "in", ids)] + + return domain + + @http.route() + def shop(self, page=0, category=None, search="", ppg=False, **post): + res = super().shop(page=page, category=category, search=search, ppg=ppg, **post) + + if ppg: + try: + ppg = int(ppg) + except ValueError: + ppg = PPG + post["ppg"] = ppg + else: + ppg = PPG + + attrib_list = request.httprequest.args.getlist("attrib") + attrib_values = [[int(x) for x in v.split("-")] for v in attrib_list if v] + attributes_ids = {v[0] for v in attrib_values} + attrib_set = {v[1] for v in attrib_values} + domain = self._get_search_domain(search, category, attrib_values) + + keep = QueryURL( + "/shop", + category=category and int(category), + search=search, + attrib=attrib_list, + order=post.get("order"), + maturity=post.get("maturity"), + version=post.get("version"), + author=post.get("author"), + ) + if post.get("version"): + field_name = ( + "product_variant_ids.product_template_attribute_value_ids" + + ".product_attribute_value_id.id" + ) + domain += [ + ( + field_name, + "=", + post.get("version"), + ) + ] + if post.get("author"): + domain += [ + ("product_variant_ids.app_author_ids.id", "=", post.get("author")) + ] + if post.get("maturity", False): + domain += [ + ( + "product_variant_ids.app_development_status", + "=", + post.get("maturity"), + ) + ] + + url = "/shop" + if search: + post["search"] = search + if attrib_list: + post["attrib"] = attrib_list + + category = request.env["product.public.category"].browse(int(category or 0)) + if category: + url = f"/shop/category/{IrHttp._slug(category)}" + + attribute_id = request.env.ref("apps_product_creator.attribute_odoo_version") + category_all = request.env["product.public.category"].search([]) + versions = request.env["product.attribute.value"].search( + [("attribute_id", "=", attribute_id.id)] + ) + authors = request.env["odoo.author"].search([]) + Product = request.env["product.template"] + + product_count = Product.search_count(domain) + pager = request.website.pager( + url=url, total=product_count, page=page, step=ppg, scope=7, url_args=post + ) + products = Product.search( + domain, + limit=ppg, + offset=pager["offset"], + order=self._get_search_order(post), + ) + + ProductAttribute = request.env["product.attribute"] + if products: + # get all products without limit + selected_products = Product.search(domain, limit=False) + attributes = ProductAttribute.search( + [("attribute_line_ids.product_tmpl_id", "in", selected_products.ids)] + ) + else: + attributes = ProductAttribute.browse(attributes_ids) + + res.qcontext.update( + { + "search": search, + "category": category, + "attrib_values": attrib_values, + "attrib_set": attrib_set, + "pager": pager, + "products": products, + "search_count": product_count, # common for all searchbox + "bins": TableCompute().process(products, ppg), + "category_all": category_all, + "versions": versions, + "authors": authors, + "version": post.get("version"), + "author": post.get("author"), + "attributes": attributes, + "keep": keep, + "maturity": post.get("maturity"), + } + ) + return res + + @http.route( + [ + '/shop/download_product_zip/' + '//' + "", + '/shop/download_product_zip//' + "", + ], + type="http", + auth="public", + website=True, + ) + def download_product_zip( + self, product_tmpl, product=False, recaptcha_token_response="", **kwargs + ): + request.params["recaptcha_token_response"] = recaptcha_token_response + try: + # The except clause below should not let what has been done inside + # here be committed. It should not either roll back everything in + # this controller method. Instead, we use a savepoint to roll back + # what has been done inside the try clause. + with request.env.cr.savepoint(): + if request.env["ir.http"]._verify_request_recaptcha_token( + "download_product_zip" + ): + return self._handle_download_product_zip(product_tmpl, product) + error = _("Suspicious activity detected by Google reCaptcha.") + except (ValidationError, UserError) as e: + error = e.args[0] + values = {"error_msg": error} + return request.render("website_apps_store.suspicious_product_download", values) + + def _handle_download_product_zip(self, product_tmpl, product): + if not product: + product = product_tmpl.get_version_info() + attachment = ( + request.env["ir.attachment"] + .sudo() + .search( + [("res_id", "=", product.id), ("res_model", "=", product._name)], + limit=1, + ) + ) + if not attachment: + product.sudo().generate_zip_file() + attachment = ( + request.env["ir.attachment"] + .sudo() + .search( + [("res_id", "=", product.id), ("res_model", "=", product._name)], + limit=1, + ) + ) + if attachment: + filecontent = base64.b64decode(attachment.datas) + disposition = f'attachment; filename="{attachment.name}"' + # increasing count for the product downloadg + product.sudo().download_count += 1 + return request.make_response( + filecontent, + [ + ("Content-Type", "application/zip, application/octet-stream"), + ("Content-Length", len(filecontent)), + ("Content-Disposition", disposition), + ], + ) + return False diff --git a/website_apps_store/i18n/es.po b/website_apps_store/i18n/es.po new file mode 100644 index 00000000..5a7fb8c6 --- /dev/null +++ b/website_apps_store/i18n/es.po @@ -0,0 +1,181 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_apps_store +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2021-08-26 03:55+0000\n" +"PO-Revision-Date: 2024-01-26 16:33+0000\n" +"Last-Translator: Ivorra78 \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Author: " +msgstr "Autor: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "License: " +msgstr "Licencia: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Maintainer: " +msgstr "Mantenedor: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Repository: " +msgstr "Repositorio: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Technical Name: " +msgstr "Nombre técnico: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Version: " +msgstr "Versión: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Website: " +msgstr "Sitio web: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "https://odoo-community.org" +msgstr "https://odoo-community.org" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.category_display +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +#: model_terms:ir.ui.view,arch_db:website_apps_store.version_display +msgid "All" +msgstr "Todas" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Alpha" +msgstr "Alfa" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Beta" +msgstr "Beta" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.category_display +msgid "Category:" +msgstr "Categoría:" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__display_name +#: model:ir.model.fields,field_description:website_apps_store.field_product_template__display_name +msgid "Display Name" +msgstr "Nombre mostrado" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "" +"Download\n" +" " +msgstr "" +"Descargar\n" +" " + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__download_count +msgid "Download Count" +msgstr "Descargas" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.sort_customize +msgid "Download Count - Max to Min" +msgstr "Descargas - Max to Min" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.sort_customize +msgid "Download Count - Min to Max" +msgstr "Descargas - Min to Max" + +#. module: website_apps_store +#. openerp-web +#: code:addons/website_apps_store/static/src/js/website_sale.js:0 +#, python-format +msgid "Error" +msgstr "Error" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.suspicious_product_download +msgid "Error during product download" +msgstr "Ocurrió un error mientras se descargaba el producto" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__id +#: model:ir.model.fields,field_description:website_apps_store.field_product_template__id +msgid "ID" +msgstr "ID" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product____last_update +#: model:ir.model.fields,field_description:website_apps_store.field_product_template____last_update +msgid "Last Modified on" +msgstr "Última modificación el" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Mature" +msgstr "Maduro" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Maturity:" +msgstr "Madurez:" + +#. module: website_apps_store +#: model:ir.model,name:website_apps_store.model_product_product +msgid "Product" +msgstr "Producto" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Product Name" +msgstr "Nombre del producto" + +#. module: website_apps_store +#: model:ir.model,name:website_apps_store.model_product_template +msgid "Product Template" +msgstr "Plantilla de producto" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Production/Stable" +msgstr "Producción/Estable" + +#. module: website_apps_store +#: code:addons/website_apps_store/controllers/main.py:0 +#, python-format +msgid "Suspicious activity detected by Google reCaptcha." +msgstr "Actividad sospechosa detectada por Google reCaptcha." + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__total_download_count +#: model:ir.model.fields,field_description:website_apps_store.field_product_template__total_download_count +msgid "Total Download Count" +msgstr "Total de descargas" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.version_display +msgid "Version:" +msgstr "Versión:" diff --git a/website_apps_store/i18n/hr.po b/website_apps_store/i18n/hr.po new file mode 100644 index 00000000..57043132 --- /dev/null +++ b/website_apps_store/i18n/hr.po @@ -0,0 +1,182 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_apps_store +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2020-03-05 18:13+0000\n" +"Last-Translator: Bole \n" +"Language-Team: none\n" +"Language: hr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 3.10\n" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Author: " +msgstr "Autor: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "License: " +msgstr "Licenca: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Maintainer: " +msgstr "Održava: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Repository: " +msgstr "Repositorij: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Technical Name: " +msgstr "Tehnički naziv: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Version: " +msgstr "Verzija: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Website: " +msgstr "Webstranica: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "https://odoo-community.org" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.category_display +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +#: model_terms:ir.ui.view,arch_db:website_apps_store.version_display +msgid "All" +msgstr "Sve" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Alpha" +msgstr "Alfa" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Beta" +msgstr "Beta" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.category_display +msgid "Category:" +msgstr "Kategorija:" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__display_name +#: model:ir.model.fields,field_description:website_apps_store.field_product_template__display_name +msgid "Display Name" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "" +"Download\n" +" " +msgstr "" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__download_count +msgid "Download Count" +msgstr "Broj preuzimanja" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.sort_customize +msgid "Download Count - Max to Min" +msgstr "Broj preuzimanja - Najviše do najmanje" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.sort_customize +msgid "Download Count - Min to Max" +msgstr "" + +#. module: website_apps_store +#. openerp-web +#: code:addons/website_apps_store/static/src/js/website_sale.js:0 +#, python-format +msgid "Error" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.suspicious_product_download +msgid "Error during product download" +msgstr "" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__id +#: model:ir.model.fields,field_description:website_apps_store.field_product_template__id +msgid "ID" +msgstr "" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product____last_update +#: model:ir.model.fields,field_description:website_apps_store.field_product_template____last_update +msgid "Last Modified on" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Mature" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Maturity:" +msgstr "" + +#. module: website_apps_store +#: model:ir.model,name:website_apps_store.model_product_product +msgid "Product" +msgstr "Proizvod" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Product Name" +msgstr "Naziv proizvoda" + +#. module: website_apps_store +#: model:ir.model,name:website_apps_store.model_product_template +msgid "Product Template" +msgstr "Predložak proizvoda" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Production/Stable" +msgstr "Produkcija/Stabilno" + +#. module: website_apps_store +#: code:addons/website_apps_store/controllers/main.py:0 +#, python-format +msgid "Suspicious activity detected by Google reCaptcha." +msgstr "" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__total_download_count +#: model:ir.model.fields,field_description:website_apps_store.field_product_template__total_download_count +msgid "Total Download Count" +msgstr "Ukupni broj preuzimanja" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.version_display +msgid "Version:" +msgstr "" + +#~ msgid "Name, Author, Version..." +#~ msgstr "Naziv, Autor, Verzija..." diff --git a/website_apps_store/i18n/it.po b/website_apps_store/i18n/it.po new file mode 100644 index 00000000..bc858046 --- /dev/null +++ b/website_apps_store/i18n/it.po @@ -0,0 +1,183 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_apps_store +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2025-01-20 11:06+0000\n" +"Last-Translator: mymage \n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.6.2\n" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Author: " +msgstr "Autore: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "License: " +msgstr "Licenza: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Maintainer: " +msgstr "Manutentore: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Repository: " +msgstr "Repository: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Technical Name: " +msgstr "Nome tecnico: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Version: " +msgstr "Versione: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Website: " +msgstr "Sito web: " + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "https://odoo-community.org" +msgstr "https://odoo-community.org" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.category_display +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +#: model_terms:ir.ui.view,arch_db:website_apps_store.version_display +msgid "All" +msgstr "Tutte" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Alpha" +msgstr "Alfa" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Beta" +msgstr "Beta" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.category_display +msgid "Category:" +msgstr "Categoria:" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__display_name +#: model:ir.model.fields,field_description:website_apps_store.field_product_template__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "" +"Download\n" +" " +msgstr "" +"Scarica\n" +" " + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__download_count +msgid "Download Count" +msgstr "Numero scaricamenti" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.sort_customize +msgid "Download Count - Max to Min" +msgstr "Conteggio download - Massimo a minimo" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.sort_customize +msgid "Download Count - Min to Max" +msgstr "Conteggio download - Minimo a massimo" + +#. module: website_apps_store +#. openerp-web +#: code:addons/website_apps_store/static/src/js/website_sale.js:0 +#, python-format +msgid "Error" +msgstr "Errore" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.suspicious_product_download +msgid "Error during product download" +msgstr "Errore nel download prodotto" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__id +#: model:ir.model.fields,field_description:website_apps_store.field_product_template__id +msgid "ID" +msgstr "ID" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product____last_update +#: model:ir.model.fields,field_description:website_apps_store.field_product_template____last_update +msgid "Last Modified on" +msgstr "Ultima modifica il" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Mature" +msgstr "Maturo" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Maturity:" +msgstr "Maturità:" + +#. module: website_apps_store +#: model:ir.model,name:website_apps_store.model_product_product +msgid "Product" +msgstr "Prodotto" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Product Name" +msgstr "Nome prodotto" + +#. module: website_apps_store +#: model:ir.model,name:website_apps_store.model_product_template +msgid "Product Template" +msgstr "Modello prodotto" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Production/Stable" +msgstr "Produzione/stabile" + +#. module: website_apps_store +#: code:addons/website_apps_store/controllers/main.py:0 +#, python-format +msgid "Suspicious activity detected by Google reCaptcha." +msgstr "Attività sospetta rilevata da Google reCaptcha." + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__total_download_count +#: model:ir.model.fields,field_description:website_apps_store.field_product_template__total_download_count +msgid "Total Download Count" +msgstr "Numero totale scaricamenti" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.version_display +msgid "Version:" +msgstr "Versione:" + +#~ msgid "Name, Author, Version..." +#~ msgstr "Nome, autore, versione..." diff --git a/website_apps_store/i18n/website_apps_store.pot b/website_apps_store/i18n/website_apps_store.pot new file mode 100644 index 00000000..5e01f35c --- /dev/null +++ b/website_apps_store/i18n/website_apps_store.pot @@ -0,0 +1,175 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * website_apps_store +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.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: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Author: " +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "License: " +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Maintainer: " +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Repository: " +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Technical Name: " +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Version: " +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Website: " +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "https://odoo-community.org" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.category_display +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +#: model_terms:ir.ui.view,arch_db:website_apps_store.version_display +msgid "All" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Alpha" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Beta" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.category_display +msgid "Category:" +msgstr "" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__display_name +#: model:ir.model.fields,field_description:website_apps_store.field_product_template__display_name +msgid "Display Name" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "" +"Download\n" +" " +msgstr "" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__download_count +msgid "Download Count" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.sort_customize +msgid "Download Count - Max to Min" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.sort_customize +msgid "Download Count - Min to Max" +msgstr "" + +#. module: website_apps_store +#. openerp-web +#: code:addons/website_apps_store/static/src/js/website_sale.js:0 +#, python-format +msgid "Error" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.suspicious_product_download +msgid "Error during product download" +msgstr "" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__id +#: model:ir.model.fields,field_description:website_apps_store.field_product_template__id +msgid "ID" +msgstr "" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product____last_update +#: model:ir.model.fields,field_description:website_apps_store.field_product_template____last_update +msgid "Last Modified on" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Mature" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Maturity:" +msgstr "" + +#. module: website_apps_store +#: model:ir.model,name:website_apps_store.model_product_product +msgid "Product" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.product +msgid "Product Name" +msgstr "" + +#. module: website_apps_store +#: model:ir.model,name:website_apps_store.model_product_template +msgid "Product Template" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.maturity_display +msgid "Production/Stable" +msgstr "" + +#. module: website_apps_store +#: code:addons/website_apps_store/controllers/main.py:0 +#, python-format +msgid "Suspicious activity detected by Google reCaptcha." +msgstr "" + +#. module: website_apps_store +#: model:ir.model.fields,field_description:website_apps_store.field_product_product__total_download_count +#: model:ir.model.fields,field_description:website_apps_store.field_product_template__total_download_count +msgid "Total Download Count" +msgstr "" + +#. module: website_apps_store +#: model_terms:ir.ui.view,arch_db:website_apps_store.version_display +msgid "Version:" +msgstr "" diff --git a/website_apps_store/models/__init__.py b/website_apps_store/models/__init__.py new file mode 100644 index 00000000..6a7d91ce --- /dev/null +++ b/website_apps_store/models/__init__.py @@ -0,0 +1,2 @@ +from . import product +from . import product_template diff --git a/website_apps_store/models/product.py b/website_apps_store/models/product.py new file mode 100644 index 00000000..ee090416 --- /dev/null +++ b/website_apps_store/models/product.py @@ -0,0 +1,10 @@ +# Copyright (C) 2017-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import fields, models + + +class ProductProduct(models.Model): + _inherit = "product.product" + + download_count = fields.Integer() diff --git a/website_apps_store/models/product_template.py b/website_apps_store/models/product_template.py new file mode 100644 index 00000000..40d40e7d --- /dev/null +++ b/website_apps_store/models/product_template.py @@ -0,0 +1,79 @@ +# Copyright (C) 2017-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +from odoo import api, fields, models + + +class ProductTemplate(models.Model): + _inherit = "product.template" + + @api.depends("product_variant_ids", "product_variant_ids.download_count") + def _compute_total_download_count(self): + for product in self: + product.total_download_count = sum( + product.mapped("product_variant_ids.download_count") + ) + + total_download_count = fields.Integer( + compute="_compute_total_download_count", store=True + ) + + def get_author_details(self): + return self.mapped("product_variant_ids.app_author_ids") + + def get_version_info(self): + products = self.product_variant_ids.sorted( + lambda a: a._get_combination_info_variant().get("attribute_seq", 0), + reverse=True, + ) + return products[0] + + def _get_combination_info( + self, + combination=False, + product_id=False, + add_qty=1, + parent_combination=False, + only_template=False, + ): + vals = super()._get_combination_info( + combination=combination, + product_id=product_id, + add_qty=add_qty, + parent_combination=parent_combination, + only_template=only_template, + ) + if not vals["product_id"]: + return vals + product = self.env["product.product"].browse(vals["product_id"]) + if product.odoo_module_id: + module_id = product.odoo_module_version_id.module_id + vals.update( + { + "is_odoo_module": True, + "name_product": product.name, + "technical_name": module_id.technical_name, + "license": product.app_license_id.name, + "license_url": product.app_license_id.website, + "author": ", ".join( + author.name for author in product.app_author_ids + ), + "website": product.app_website, + "repository": product.app_github_url, + "rst_html": product.app_description_rst_html, + "app_summary": product.app_summary, + "attribute_seq": combination.attribute_id.sequence, + } + ) + return vals + + def _get_first_possible_combination( + self, parent_combination=None, necessary_values=None + ): + """Override method to load last version first in app store""" + values = list( + self._get_possible_combinations(parent_combination, necessary_values) + ) + if not any(values): + return self.env["product.template.attribute.value"] + return values[-1] diff --git a/website_apps_store/pyproject.toml b/website_apps_store/pyproject.toml new file mode 100644 index 00000000..4231d0cc --- /dev/null +++ b/website_apps_store/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/website_apps_store/readme/CONTRIBUTORS.md b/website_apps_store/readme/CONTRIBUTORS.md new file mode 100644 index 00000000..0498bea5 --- /dev/null +++ b/website_apps_store/readme/CONTRIBUTORS.md @@ -0,0 +1,8 @@ +- Ruchir Shukla \< +- Divya Modi \<\> +- Eric Caudal \<\> +- Oscar Alcala \<\> +- [Tecnativa](https://www.tecnativa.com): + - Víctor M.M. Torres + - Alexandre D. Díaz + - Ernesto Tejeda diff --git a/website_apps_store/readme/DESCRIPTION.md b/website_apps_store/readme/DESCRIPTION.md new file mode 100644 index 00000000..e7858072 --- /dev/null +++ b/website_apps_store/readme/DESCRIPTION.md @@ -0,0 +1,3 @@ +Providing facility for displaying the module specific information in a +standard Odoo e-commerce website (front-end) and download the zip file +of the selected product. diff --git a/website_apps_store/static/description/icon.png b/website_apps_store/static/description/icon.png new file mode 100644 index 00000000..3a0328b5 Binary files /dev/null and b/website_apps_store/static/description/icon.png differ diff --git a/website_apps_store/static/description/index.html b/website_apps_store/static/description/index.html new file mode 100644 index 00000000..dac57a8b --- /dev/null +++ b/website_apps_store/static/description/index.html @@ -0,0 +1,434 @@ + + + + + +Website Apps Store + + + +
+

Website Apps Store

+ + +

Beta License: AGPL-3 OCA/apps-store Translate me on Weblate Try me on Runboat

+

Providing facility for displaying the module specific information in a +standard Odoo e-commerce website (front-end) and download the zip file +of the selected product.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • BizzAppDev
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

This module is part of the OCA/apps-store project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/website_apps_store/static/src/js/website_apps_store_tour.js b/website_apps_store/static/src/js/website_apps_store_tour.js new file mode 100644 index 00000000..6d89d121 --- /dev/null +++ b/website_apps_store/static/src/js/website_apps_store_tour.js @@ -0,0 +1,155 @@ +/** @odoo-module **/ + +import {registry} from "@web/core/registry"; + +const tour = registry.category("web_tour.tours"); + +tour.add("successfully_download_zip", { + name: "Download Zip File - successfully", + url: "/shop/page/2", + test: true, + steps: [ + { + content: "Shop", + trigger: ".oe_product_cart a:contains('Odoo Module')", + run: "click", + }, + { + content: "Select Version", + trigger: "input[type=radio]", + run() { + const radios = document.querySelectorAll("input[type='radio']"); + if (radios.length) { + radios[radios.length - 1].checked = true; + } + }, + }, + { + content: "Download", + trigger: "#download_zip", + run: "click", + }, + { + content: "No failure, we are in the same page", + trigger: "#product_detail", + }, + ], +}); + +tour.add("download_zip_failed", { + name: "Download Zip File - Failed", + url: "/shop/page/2", + test: true, + steps: [ + { + content: "Shop", + trigger: ".oe_product_cart a:contains('Odoo Module')", + run: "click", + }, + { + content: "Select Version", + trigger: "input[type=radio]", + run() { + const radios = document.querySelectorAll("input[type='radio']"); + if (radios.length) { + radios[radios.length - 1].checked = true; + } + }, + }, + { + content: "Download", + trigger: "#download_zip", + run: "click", + }, + { + content: "Suspicious", + trigger: "#wrap.wrap-download-zip-failed", + }, + ], +}); + +tour.add("select_version_search", { + name: "Select Version", + url: "/shop", + test: true, + steps: [ + { + content: "Shop", + trigger: ".dropdown_version_by a.dropdown-toggle", + run: "click", + }, + { + content: "Select Version", + trigger: ".dropdown_version_by .dropdown-menu a:contains('10.0')", + run: "click", + }, + ], +}); + +tour.add("select_category_search", { + name: "Select Category", + url: "/shop", + test: true, + steps: [ + { + content: "Shop", + trigger: ".dropdown_category_by a.dropdown-toggle", + run: "click", + }, + { + content: "Select Category", + trigger: ".dropdown_category_by .dropdown-menu a:contains('Category')", + run: "click", + }, + ], +}); + +tour.add("module_search", { + name: "Select Product(Module)", + url: "/shop", + test: true, + steps: [ + { + content: "Shop", + trigger: ".search-query", + run() { + const el = document.querySelector(".search-query"); + if (el) el.value = "Test"; + }, + }, + { + content: "Search Button", + trigger: ".oe_search_button", + run: "click", + }, + { + content: "There is one or more products as a search result", + trigger: "#products_grid td.oe_product a:contains('Odoo Module')", + }, + ], +}); + +tour.add("technical_name_search", { + name: "Select Product(Module) by Technical Name", + url: "/shop", + test: true, + steps: [ + { + content: "Shop", + trigger: ".search-query", + run() { + const el = document.querySelector(".search-query"); + if (el) el.value = "odoo_module"; + }, + }, + { + content: "Search Button", + trigger: ".oe_search_button", + run: "click", + }, + { + content: "There is one or more products as a search result", + trigger: "#products_grid td.oe_product a:contains('Odoo Module')", + }, + ], +}); diff --git a/website_apps_store/static/src/js/website_sale.js b/website_apps_store/static/src/js/website_sale.js new file mode 100644 index 00000000..4e9ddc78 --- /dev/null +++ b/website_apps_store/static/src/js/website_sale.js @@ -0,0 +1,102 @@ +/** + * Copyright 2018 BizzAppDev + * License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + **/ +/** @odoo-module **/ + +import "web.dom_ready"; +import publicWidget from "@web/legacy/js/public/public_widget"; +import {_t} from "@web/core/l10n/translation"; +import {ReCaptcha} from "google_recaptcha.ReCaptchaV3"; + +const WebsiteSale = publicWidget.registry.WebsiteSale; + +WebsiteSale.include({ + // use legacy widget 'events' in Odoo 18 + events: Object.assign({}, WebsiteSale.prototype.events, { + "click #download_zip": "_onClickDownload", + }), + + init: function () { + this._super.apply(this, arguments); + this._recaptcha = new ReCaptcha(); + this.__started = new Promise((resolve) => (this.__startResolve = resolve)); + }, + + willStart: function () { + const res = this._super(...arguments); + this._recaptchaLoaded = true; + this._recaptcha.loadLibs(); + return res; + }, + + _onChangeCombination: function (ev, $parent, combination) { + this._super.apply(this, arguments); + if ("is_odoo_module" in combination && combination.is_odoo_module) { + // fixed selector to match template class 'tech_detail' + const $tech_detail = this.$(".tech_detail"); + const $license_detail = this.$(".license_detail"); + const $license_url = this.$(".license_url"); + const $author_detail = this.$(".author_detail"); + const $website_detail = this.$(".website_detail"); + const $website_detail_href = this.$("#website_detail_href"); + const $repo_detail = this.$(".repo_detail"); + const $rst_html = this.$(".desc_rst"); + const $app_summary = this.$(".app_summary"); + const $name_product = this.$(".name_product"); + + $tech_detail.text(combination.technical_name); + $license_detail.text(combination.license); + $license_url.attr("href", combination.license_url); + $author_detail.text(combination.author); + $website_detail.text(combination.website); + $website_detail_href.attr("href", combination.website); + $repo_detail.text(combination.repository); + if ($repo_detail.length) { + $repo_detail.parent()[0].href = combination.repository; + } + $rst_html.html(combination.rst_html); + $app_summary.text(combination.app_summary); + $name_product.text(combination.name_product); + } + }, + + _onClickDownload: async function (ev) { + ev.preventDefault(); + // Prevent users from crazy clicking + this.$("#download_zip").addClass("disabled").attr("disabled", "disabled"); + + let recaptcha_token_response = ""; + if (this._recaptchaLoaded) { + const tokenObj = await this._recaptcha.getToken("download_product_zip"); + if (tokenObj.token) { + recaptcha_token_response = tokenObj.token; + } else if (tokenObj.error) { + this.displayNotification({ + type: "danger", + title: _t("Error"), + message: tokenObj.error, + sticky: true, + }); + return false; + } + } + const product_template_id = this.$(".product_template_id").val(); + const product_id = this.$(".product_id").val(); + if (product_id) { + window.location.href = + "/shop/download_product_zip/" + + product_template_id + + "/" + + product_id + + "/" + + recaptcha_token_response; + } else { + window.location.href = + "/shop/download_product_zip/" + + product_template_id + + "/" + + recaptcha_token_response; + } + }, +}); diff --git a/website_apps_store/static/src/scss/main.scss b/website_apps_store/static/src/scss/main.scss new file mode 100644 index 00000000..27687e95 --- /dev/null +++ b/website_apps_store/static/src/scss/main.scss @@ -0,0 +1,33 @@ +.desc_rst > { + .document > .reference { + display: none; + } +} + +.font_12 { + font-size: 12px; +} + +.dropdown-scrollable { + max-height: 15rem; + overflow-y: auto; +} + +#product_details .col-form-label { + padding-top: 0; + padding-bottom: 0; +} + +#o-carousel-product { + .carousel-outer { + height: unset; + } +} + +#product_detail[data-is-module="1"] + #o-carousel-product + .carousel-outer + .carousel-inner + img { + width: auto; +} diff --git a/website_apps_store/tests/__init__.py b/website_apps_store/tests/__init__.py new file mode 100644 index 00000000..34a97dc5 --- /dev/null +++ b/website_apps_store/tests/__init__.py @@ -0,0 +1,2 @@ +from . import test_website_apps_store +from . import test_tour_website_apps_store diff --git a/website_apps_store/tests/test_tour_website_apps_store.py b/website_apps_store/tests/test_tour_website_apps_store.py new file mode 100644 index 00000000..fd4d37e4 --- /dev/null +++ b/website_apps_store/tests/test_tour_website_apps_store.py @@ -0,0 +1,105 @@ +# Copyright 2017-2018 BizzAppDev +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). + +import os +from unittest import mock + +from odoo.tests import HttpCase, tagged + +mock_get_module_path = ( + "odoo.addons.apps_download.models.product_product.ProductProduct._get_module_path" +) +mock_verify_recaptcha_token = ( + "odoo.addons.google_recaptcha.models.ir_http.Http._verify_recaptcha_token" +) + + +@tagged("post_install", "-at_install") +class TestUi(HttpCase): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.env.ref("website_sale.products").active = True + cls._req_patcher = mock.patch( + "odoo.addons.github_connector_odoo.models.github_repository.requests.get" + ) + cls._mock_get = cls._req_patcher.start() + cls.addClassCleanup(cls._req_patcher.stop) + resp = mock.MagicMock() + resp.status_code = 200 + resp.text = "login/Repository1 1234\n" + resp.json.return_value = ["login/Repository1 1234"] + resp.iter_lines.return_value = [b"login/Repository1 1234"] + resp.raise_for_status.return_value = None + resp.__iter__.return_value = iter([b"login/Repository1 1234"]) + cls._mock_get.return_value = resp + + cls.env["product.public.category"].create({"name": "Category"}) + cls.organization = cls.env.ref("github_connector.oca_organization") + + cls.organization_serie = cls.env["github.organization.serie"].create( + {"name": "14.0", "sequence": 1, "organization_id": cls.organization.id} + ) + cls.repository = cls.env["github.repository"].create( + {"name": "Repository1", "organization_id": cls.organization.id} + ) + cls.branch = cls.env["github.repository.branch"].create( + { + "name": "14.0", + "repository_id": cls.repository.id, + "organization_id": cls.organization.id, + } + ) + cls.odoo_module = cls.env["odoo.module"].create( + {"technical_name": "odoo_module"} + ) + cls.attribute = cls.env.ref("apps_product_creator.attribute_odoo_version") + cls.version = cls.env.ref("apps_product_creator.odoo_version_140") + cls.env["odoo.module.version"].create( + { + "name": "Odoo Module", + "technical_name": "odoo_module", + "module_id": cls.odoo_module.id, + "repository_branch_id": cls.branch.id, + "license": "AGPL-3", + "summary": "Summary Test", + "website": "Website Test", + "description_rst": "Description Test", + "version": "14.0", + "author": "OCA", + "depends": "base", + "external_dependencies": "{}", + } + ) + cls.odoo_module.action_create_product() + + def test_successfully_download_zip_tour(self): + test_path = os.path.dirname(os.path.realpath(__file__)) + test_path = test_path.split("/website_apps_store")[0] + test_module_path = os.path.join( + test_path + "/apps_download" + "/tests", "test_modules", "second_module" + ) + with mock.patch(mock_get_module_path) as mock_mod_path: + mock_mod_path.return_value = test_module_path + with mock.patch(mock_verify_recaptcha_token) as mock_verify: + mock_verify.return_value = "is_human" + self.start_tour( + "/shop/page/2", "successfully_download_zip", login="admin" + ) + + def test_download_zip_failed_tour(self): + with mock.patch(mock_verify_recaptcha_token) as mock_verify: + mock_verify.return_value = "is_bot" + self.start_tour("/shop/page/2", "download_zip_failed", login="admin") + + def test_select_version_search_tour(self): + self.start_tour("/shop", "select_version_search", login="admin") + + def test_select_category_search_tour(self): + self.start_tour("/shop", "select_category_search", login="admin") + + def test_module_search_tour(self): + self.start_tour("/shop", "module_search", login="admin") + + def test_technical_name_search_tour(self): + self.start_tour("/shop", "technical_name_search", login="admin") diff --git a/website_apps_store/tests/test_website_apps_store.py b/website_apps_store/tests/test_website_apps_store.py new file mode 100644 index 00000000..c9a4ab8a --- /dev/null +++ b/website_apps_store/tests/test_website_apps_store.py @@ -0,0 +1,64 @@ +# Copyright (C) 2018-Today: Odoo Community Association (OCA) +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). +from odoo.tests.common import TransactionCase + + +class TestWebsiteAppsStore(TransactionCase): + def setUp(self): + super().setUp() + + self.organization2 = self.env["github.organization"].create( + {"name": "Organization 2", "github_name": "login"} + ) + + self.organization_serie2 = self.env["github.organization.serie"].create( + {"name": "12.0", "sequence": 1, "organization_id": self.organization2.id} + ) + + self.repository2 = self.env["github.repository"].create( + {"name": "Repository1", "organization_id": self.organization2.id} + ) + + self.branch2 = self.env["github.repository.branch"].create( + { + "name": "12.0", + "repository_id": self.repository2.id, + "organization_id": self.organization2.id, + } + ) + + self.odoo_module2 = self.env["odoo.module"].create( + {"technical_name": "odoo_module2"} + ) + + self.attribute = self.env.ref("apps_product_creator.attribute_odoo_version") + self.version = self.env.ref("apps_product_creator.odoo_version_100") + + self.odoo_module2_version2 = self.env["odoo.module.version"].create( + { + "name": "Odoo Module 2", + "technical_name": "odoo_module2", + "module_id": self.odoo_module2.id, + "repository_branch_id": self.branch2.id, + "license": "AGPL-3", + "summary": "Summary Test", + "website": "Website Test", + "description_rst": "Description Test", + "version": "10.0", + "author": "OCA", + "depends": "base", + "external_dependencies": "{}", + } + ) + + def test_product_author_version_info(self): + self.assertFalse(self.odoo_module2.product_template_id) + self.odoo_module2.action_create_product() + self.assertTrue(self.odoo_module2.product_template_id) + action = self.odoo_module2.action_view_products() + self.assertEqual( + self.odoo_module2.product_template_id.product_variant_ids.ids[0], + action["res_id"], + ) + self.odoo_module2.product_template_id.get_author_details() + self.odoo_module2.product_template_id.get_version_info() diff --git a/website_apps_store/views/suspicious_templates.xml b/website_apps_store/views/suspicious_templates.xml new file mode 100644 index 00000000..cfd8220d --- /dev/null +++ b/website_apps_store/views/suspicious_templates.xml @@ -0,0 +1,47 @@ + + + + + diff --git a/website_apps_store/views/templates.xml b/website_apps_store/views/templates.xml new file mode 100644 index 00000000..c8f9db64 --- /dev/null +++ b/website_apps_store/views/templates.xml @@ -0,0 +1,507 @@ + + + + + + + + + + + + + + + + + + + + + + + + + +