You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
165 lines
6.0 KiB
165 lines
6.0 KiB
# Copyright 2019 Alexandre Díaz <dev@redneboa.es>
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
import base64
|
|
import time
|
|
from colorsys import rgb_to_hls, hls_to_rgb
|
|
from odoo import models, fields, api
|
|
from ..utils import image_to_rgb, convert_to_image, n_rgb_to_hex
|
|
|
|
|
|
URL_BASE = '/web_company_color/static/src/scss/'
|
|
URL_SCSS_GEN_TEMPLATE = URL_BASE + 'custom_colors.%d.%s.gen.scss'
|
|
|
|
|
|
class ResCompany(models.Model):
|
|
_inherit = 'res.company'
|
|
|
|
SCSS_TEMPLATE = """
|
|
.o_main_navbar {
|
|
background-color: %(color_navbar_bg)s !important;
|
|
color: %(color_navbar_text)s !important;
|
|
|
|
> .o_menu_brand {
|
|
color: %(color_navbar_text)s !important;
|
|
&:hover, &:focus, &:active, &:focus:active {
|
|
background-color: %(color_navbar_bg_hover)s !important;
|
|
}
|
|
}
|
|
|
|
.show {
|
|
.dropdown-toggle {
|
|
background-color: %(color_navbar_bg_hover)s !important;
|
|
}
|
|
}
|
|
|
|
> ul {
|
|
> li {
|
|
> a, > label {
|
|
color: %(color_navbar_text)s !important;
|
|
|
|
&:hover, &:focus, &:active, &:focus:active {
|
|
background-color: %(color_navbar_bg_hover)s !important;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
"""
|
|
|
|
company_colors = fields.Serialized()
|
|
color_navbar_bg = fields.Char('Navbar Background Color',
|
|
sparse='company_colors')
|
|
color_navbar_bg_hover = fields.Char(
|
|
'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
|
|
def create(self, values):
|
|
record = super().create(values)
|
|
record.scss_create_or_update_attachment()
|
|
return record
|
|
|
|
@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()),
|
|
]).sudo().unlink()
|
|
return result
|
|
|
|
@api.multi
|
|
def write(self, values):
|
|
if not self.env.context.get('ignore_company_color', False):
|
|
fields_to_check = ('color_navbar_bg',
|
|
'color_navbar_bg_hover',
|
|
'color_navbar_text')
|
|
if 'logo' in values:
|
|
if values['logo']:
|
|
_r, _g, _b = image_to_rgb(convert_to_image(values['logo']))
|
|
# Make color 10% darker
|
|
_h, _l, _s = rgb_to_hls(_r, _g, _b)
|
|
_l = max(0, _l - 0.1)
|
|
_rd, _gd, _bd = hls_to_rgb(_h, _l, _s)
|
|
# Calc. optimal text color (b/w)
|
|
# Grayscale human vision perception (Rec. 709 values)
|
|
_a = 1 - (0.2126 * _r + 0.7152 * _g + 0.0722 * _b)
|
|
values.update({
|
|
'color_navbar_bg': n_rgb_to_hex(_r, _g, _b),
|
|
'color_navbar_bg_hover': n_rgb_to_hex(_rd, _gd, _bd),
|
|
'color_navbar_text': '#000' if _a < 0.5 else '#fff',
|
|
})
|
|
else:
|
|
values.update(self.default_get(fields_to_check))
|
|
|
|
result = super().write(values)
|
|
|
|
if any([field in values for field in fields_to_check]):
|
|
self.scss_create_or_update_attachment()
|
|
else:
|
|
result = super().write(values)
|
|
return result
|
|
|
|
@api.multi
|
|
def _scss_get_sanitized_values(self):
|
|
self.ensure_one()
|
|
values = dict(self.company_colors)
|
|
values.update({
|
|
'color_navbar_bg': values['color_navbar_bg'] or '$o-brand-odoo',
|
|
'color_navbar_bg_hover': values['color_navbar_bg_hover']
|
|
or '$o-navbar-inverse-link-hover-bg',
|
|
'color_navbar_text': values['color_navbar_text'] or '#FFF',
|
|
})
|
|
return values
|
|
|
|
@api.multi
|
|
def _scss_generate_content(self):
|
|
self.ensure_one()
|
|
# ir.attachment need files with content to work
|
|
if not self.company_colors:
|
|
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.<company_id>
|
|
def _scss_get_url_simplified(self):
|
|
self.ensure_one()
|
|
NTEMPLATE = '.'.join(URL_SCSS_GEN_TEMPLATE.split('.')[:2])
|
|
return NTEMPLATE % 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']
|
|
modif_timestamp = str(int(time.time())) # One second resolution
|
|
for record in self:
|
|
datas = base64.b64encode(
|
|
record._scss_generate_content().encode('utf-8'))
|
|
custom_attachment = IrAttachmentObj.sudo().search([
|
|
('url', 'like', '%s%%' % record._scss_get_url_simplified())
|
|
])
|
|
custom_url = record.scss_get_url(timestamp=modif_timestamp)
|
|
values = {
|
|
'datas': datas,
|
|
'url': custom_url,
|
|
'name': custom_url,
|
|
'datas_fname': custom_url.split("/")[-1],
|
|
}
|
|
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()
|