From 11eca19d10e22afc4f96766d68fda4d0aad4c1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexandre=20D=C3=ADaz?= Date: Thu, 19 Mar 2020 15:04:49 +0100 Subject: [PATCH] [MIG] web_widget_color: Migration to 13.0 --- web_company_color/__manifest__.py | 2 +- web_company_color/hooks.py | 2 +- web_company_color/models/__init__.py | 2 + web_company_color/models/assetsbundle.py | 14 ++++ web_company_color/models/ir_qweb.py | 86 +++++++++++++++++++++++ web_company_color/models/res_company.py | 38 +++------- web_company_color/readme/CONTRIBUTORS.rst | 4 +- web_company_color/view/assets.xml | 20 ++---- 8 files changed, 122 insertions(+), 46 deletions(-) create mode 100644 web_company_color/models/assetsbundle.py create mode 100644 web_company_color/models/ir_qweb.py diff --git a/web_company_color/__manifest__.py b/web_company_color/__manifest__.py index f5869b6eb..219ab9178 100644 --- a/web_company_color/__manifest__.py +++ b/web_company_color/__manifest__.py @@ -8,7 +8,7 @@ "version": "13.0.1.0.0", "author": "Alexandre Díaz, " "Odoo Community Association (OCA)", "website": "https://github.com/OCA/web", - "depends": ["web", "base_sparse_field", "web_widget_color"], + "depends": ["web", "base_sparse_field"], "data": ["view/assets.xml", "view/res_company.xml"], "uninstall_hook": "uninstall_hook", "post_init_hook": "post_init_hook", diff --git a/web_company_color/hooks.py b/web_company_color/hooks.py index a2d07f89f..ca23677bf 100644 --- a/web_company_color/hooks.py +++ b/web_company_color/hooks.py @@ -7,7 +7,7 @@ from .models.res_company import URL_BASE def uninstall_hook(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) - env["ir.attachment"].search([("url", "like", "%s%%" % URL_BASE)]).unlink() + env["ir.attachment"].search([("url", "=like", "%s%%" % URL_BASE)]).unlink() def post_init_hook(cr, registry): diff --git a/web_company_color/models/__init__.py b/web_company_color/models/__init__.py index a12c1b8ee..8677b09f5 100644 --- a/web_company_color/models/__init__.py +++ b/web_company_color/models/__init__.py @@ -1,3 +1,5 @@ # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import assetsbundle from . import res_company +from . import ir_qweb diff --git a/web_company_color/models/assetsbundle.py b/web_company_color/models/assetsbundle.py new file mode 100644 index 000000000..d6c31c2be --- /dev/null +++ b/web_company_color/models/assetsbundle.py @@ -0,0 +1,14 @@ +# Copyright 2020 Alexandre Díaz +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo.addons.base.models.assetsbundle import AssetsBundle, ScssStylesheetAsset + + +class AssetsBundleCompanyColor(AssetsBundle): + def get_company_color_asset_node(self): + """ Process the user active company scss and returns the node to inject """ + company_id = self.env["res.company"].browse( + self.env.context.get("active_company_id", 0) + ) + asset = ScssStylesheetAsset(self, url=company_id.scss_get_url()) + compiled = self.compile_css(asset.compile, asset.get_source()) + return ("style", {}, compiled) diff --git a/web_company_color/models/ir_qweb.py b/web_company_color/models/ir_qweb.py new file mode 100644 index 000000000..869e040b3 --- /dev/null +++ b/web_company_color/models/ir_qweb.py @@ -0,0 +1,86 @@ +# Copyright 2020 Alexandre Díaz +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from inspect import unwrap + +from odoo import api, models, tools +from odoo.http import request + +from odoo.addons.base.models.ir_qweb import IrQWeb + +from .assetsbundle import AssetsBundleCompanyColor + +# Monkey Patch to change the ormcache_context decorator of '_get_asset_nodes' to +# add 'active_company_id' context key. This is done to avoid "clear_caches" usage +# that works in a more aggressive way to the LRU cache. + +_orig_get_asset_nodes = unwrap(IrQWeb._get_asset_nodes) + + +@tools.conditional( + "xml" not in tools.config["dev_mode"], + tools.ormcache_context( + "xmlid", + 'options.get("lang", "en_US")', + "css", + "js", + "debug", + "async_load", + "defer_load", + "lazy_load", + keys=("website_id", "active_company_id"), + ), +) +def _get_asset_nodes__mp( + self, + xmlid, + options, + css=True, + js=True, + debug=False, + async_load=False, + defer_load=False, + lazy_load=False, + values=None, +): + return _orig_get_asset_nodes( + self, + xmlid, + options, + css=css, + js=js, + debug=debug, + async_load=async_load, + defer_load=defer_load, + lazy_load=lazy_load, + values=values, + ) + + +IrQWeb._get_asset_nodes = _get_asset_nodes__mp + + +class QWeb(models.AbstractModel): + _inherit = "ir.qweb" + + @api.model + def render(self, id_or_xml_id, values=None, **options): + """ Adds the active company to the context """ + try: + active_company_id = int( + request.httprequest.cookies.get("cids", "").split(",")[0] + ) + except Exception: + active_company_id = False + company_id = ( + self.env["res.company"].browse(active_company_id) + or self.env.user.company_id + ) + self = self.with_context(active_company_id=company_id.id) + return super().render(id_or_xml_id, values=values, **options) + + def _get_asset_content(self, xmlid, options): + """ Handle 'special' web_company_color xmlid """ + if xmlid == "web_company_color.company_color_assets": + asset = AssetsBundleCompanyColor(xmlid, [], env=self.env) + return ([], [asset.get_company_color_asset_node()]) + return super()._get_asset_content(xmlid, options) diff --git a/web_company_color/models/res_company.py b/web_company_color/models/res_company.py index 622a73477..a458b25f1 100644 --- a/web_company_color/models/res_company.py +++ b/web_company_color/models/res_company.py @@ -1,7 +1,6 @@ # Copyright 2019 Alexandre Díaz # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). import base64 -import time from colorsys import hls_to_rgb, rgb_to_hls from odoo import api, fields, models @@ -9,7 +8,7 @@ from odoo import api, fields, models from ..utils import convert_to_image, image_to_rgb, n_rgb_to_hex URL_BASE = "/web_company_color/static/src/scss/" -URL_SCSS_GEN_TEMPLATE = URL_BASE + "custom_colors.%d.%s.gen.scss" +URL_SCSS_GEN_TEMPLATE = URL_BASE + "custom_colors.%d.gen.scss" class ResCompany(models.Model): @@ -53,7 +52,6 @@ class ResCompany(models.Model): "Navbar Background Color Hover", sparse="company_colors" ) color_navbar_text = fields.Char("Navbar Text Color", sparse="company_colors") - scss_modif_timestamp = fields.Char("SCSS Modif. Timestamp") @api.model_create_multi def create(self, vals_list): @@ -61,17 +59,14 @@ class ResCompany(models.Model): records.scss_create_or_update_attachment() return records - @api.multi def unlink(self): - result = super().unlink() IrAttachmentObj = self.env["ir.attachment"] for record in self: IrAttachmentObj.sudo().search( - [("url", "like", "%s%%" % record._scss_get_url_simplified())] + [("url", "=", record.scss_get_url()), ("company_id", "=", record.id)] ).sudo().unlink() - return result + return super().unlink() - @api.multi def write(self, values): if not self.env.context.get("ignore_company_color", False): fields_to_check = ( @@ -107,7 +102,6 @@ class ResCompany(models.Model): result = super().write(values) return result - @api.multi def _scss_get_sanitized_values(self): self.ensure_one() # Clone company_color as dictionary to avoid ORM operations @@ -126,7 +120,6 @@ class ResCompany(models.Model): ) return values - @api.multi def _scss_generate_content(self): self.ensure_one() # ir.attachment need files with content to work @@ -134,41 +127,28 @@ class ResCompany(models.Model): return "// No Web Company Color SCSS Content\n" return self.SCSS_TEMPLATE % self._scss_get_sanitized_values() - # URL to scss related with this company, without timestamp - # /web_company_color/static/src/scss/custom_colors. - def _scss_get_url_simplified(self): + def scss_get_url(self): self.ensure_one() - NTEMPLATE = ".".join(URL_SCSS_GEN_TEMPLATE.split(".")[:2]) - return NTEMPLATE % self.id + return URL_SCSS_GEN_TEMPLATE % self.id - @api.multi - def scss_get_url(self, timestamp=None): - self.ensure_one() - return URL_SCSS_GEN_TEMPLATE % (self.id, timestamp or self.scss_modif_timestamp) - - @api.multi def scss_create_or_update_attachment(self): IrAttachmentObj = self.env["ir.attachment"] - # The time window is 1 second - # This mean that all modifications realized in that second will - # have the same timestamp - modif_timestamp = str(int(time.time())) for record in self: datas = base64.b64encode(record._scss_generate_content().encode("utf-8")) + custom_url = record.scss_get_url() custom_attachment = IrAttachmentObj.sudo().search( - [("url", "like", "%s%%" % record._scss_get_url_simplified())] + [("url", "=", custom_url), ("company_id", "=", record.id)] ) - custom_url = record.scss_get_url(timestamp=modif_timestamp) values = { "datas": datas, + "db_datas": datas, "url": custom_url, "name": custom_url, - "datas_fname": custom_url.split("/")[-1], + "company_id": record.id, } if custom_attachment: custom_attachment.sudo().write(values) else: values.update({"type": "binary", "mimetype": "text/scss"}) IrAttachmentObj.sudo().create(values) - self.write({"scss_modif_timestamp": modif_timestamp}) self.env["ir.qweb"].sudo().clear_caches() diff --git a/web_company_color/readme/CONTRIBUTORS.rst b/web_company_color/readme/CONTRIBUTORS.rst index 1cb0a6535..09be7ad09 100644 --- a/web_company_color/readme/CONTRIBUTORS.rst +++ b/web_company_color/readme/CONTRIBUTORS.rst @@ -1,4 +1,4 @@ -* Jordi Ballester Alomar (Eficent) -* Lois Rilo (Eficent) +* Jordi Ballester Alomar (ForgeFlow) +* Lois Rilo (ForgeFlow) * Simone Orsi * Jairo Llopis diff --git a/web_company_color/view/assets.xml b/web_company_color/view/assets.xml index 545771286..94b3bafc2 100644 --- a/web_company_color/view/assets.xml +++ b/web_company_color/view/assets.xml @@ -4,22 +4,16 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). --> +