Merge PR #2770 into 17.0

Signed-off-by pedrobaeza
pull/2807/head
OCA-git-bot 2024-04-18 19:18:46 +00:00
commit a53d39bca3
16 changed files with 830 additions and 0 deletions

View File

@ -0,0 +1,120 @@
====================
Custom shortcut icon
====================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:4af1c92721d131728f92364370ba5145f45bac9b8e4d4396572737b9ccacd56e
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |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%2Fweb-lightgray.png?logo=github
:target: https://github.com/OCA/web/tree/17.0/web_favicon
:alt: OCA/web
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/web-17-0/web-17-0-web_favicon
: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/web&target_branch=17.0
:alt: Try me on Runboat
|badge1| |badge2| |badge3| |badge4| |badge5|
This module was written to allow you to customize your Odoo instance's
shortcut icon (aka favicon). This is useful for branding purposes, but
also for integrators who have many different Odoo instances running and
need to see at a glance which browser tab does what.
The icon is shown also for portal users when the website modules are not
installed.
More info about favicon: https://en.wikipedia.org/wiki/Favicon
**Table of contents**
.. contents::
:local:
Configuration
=============
Upload your favicon (16x16, 32x32, 64x64 or "as big as possible") on the
company form. The file format would be ico, gif or png with 16x16, 32x32
or 64x64 pixels and 16 colors. Highers resolutions or colors support
depends on the used browser, but most modern browsers do.
Note that most browsers cache favicons basically forever, so if you want
your icon to show up, you'll most probably have to delete you browser
cache. Some browsers can refresh the favicon, accessing the URL
<base_url>/web_favicon/favicon.
You have a sample SVG that can be used as template for generating your
icon in /static/src/img/master_original_favicon.svg. You can also search
for some favicon generators across the web.
To allow a user to edit the favicon it has to be member of group
"Administration / Settings".
Known issues / Roadmap
======================
- Allow to upload some big icon (preferrably SVG or the like) and
generate all the icons from it
- Generate icons suitable for mobile devices and web apps (see
/static/src/img/ folder inside the module for a sample of the
possible current formats.
- Put the icon definition at system level, not at company level. It
doesn't make sense (as the icon is cached) to have a different icon
per company.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/web/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 <https://github.com/OCA/web/issues/new?body=module:%20web_favicon%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
-------
* Therp BV
* Tecnativa
* OERP Canada
Contributors
------------
- OERP Canada <https://www.oerp.ca/>:
- Daryl Chen <dc@oerp.ca>
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/web <https://github.com/OCA/web/tree/17.0/web_favicon>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

View File

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import models

View File

@ -0,0 +1,22 @@
# Copyright 2015 Therp BV <http://therp.nl>
# Copyright 2016 Pedro M. Baeza
# Copyright 2024 OERP Canada <https://www.oerp.ca>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
"name": "Custom shortcut icon",
"version": "17.0.1.0.0",
"author": "Therp BV, "
"Tecnativa, "
"OERP Canada,"
"Odoo Community Association (OCA)",
"license": "AGPL-3",
"category": "Website",
"summary": "Allows to set a custom shortcut icon (aka favicon)",
"website": "https://github.com/OCA/web",
"depends": [
"web",
],
"data": ["views/res_company_views.xml", "views/templates.xml"],
"installable": True,
}

View File

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import res_company

View File

@ -0,0 +1,87 @@
# Copyright 2015 Therp BV <http://therp.nl>
# Copyright 2016 Pedro M. Baeza
# Copyright 2024 OERP Canada <https://www.oerp.ca>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import base64
import hashlib
import io
from random import randrange
from PIL import Image
import odoo
from odoo import api, fields, models, tools
from odoo.http import request
class ResCompany(models.Model):
_inherit = "res.company"
def _get_default_favicon(self, original=False):
img_path = odoo.tools.misc.file_path("web/static/img/favicon.ico")
with tools.file_open(img_path, "rb") as f:
if original:
return base64.b64encode(f.read())
# Modify the source image to add a colored bar on the bottom
# This could seem overkill to modify the pixels 1 by 1, but
# Pillow doesn't provide an easy way to do it, and this
# is acceptable for a 16x16 image.
color = (
randrange(32, 224, 24),
randrange(32, 224, 24),
randrange(32, 224, 24),
)
original = Image.open(f)
new_image = Image.new("RGBA", original.size)
height = original.size[1]
width = original.size[0]
bar_size = 1
for y in range(height):
for x in range(width):
pixel = original.getpixel((x, y))
if height - bar_size <= y + 1 <= height:
new_image.putpixel((x, y), (color[0], color[1], color[2], 255))
else:
new_image.putpixel(
(x, y), (pixel[0], pixel[1], pixel[2], pixel[3])
)
stream = io.BytesIO()
new_image.save(stream, format="ICO")
return base64.b64encode(stream.getvalue())
favicon = fields.Binary(
string="Company Favicon",
help="This field holds the image used to display favicon for a given company.",
default=_get_default_favicon,
)
@api.model_create_multi
def create(self, vals_list):
# add default favicon
for vals in vals_list:
if not vals.get("favicon"):
vals["favicon"] = self._get_default_favicon()
return super().create(vals_list)
# Get favicon from current company
@api.model
def _get_favicon(self):
"""Returns a local url that points to the image field of a given record."""
company_id = (
request.httprequest.cookies.get("cids")
if request.httprequest.cookies.get("cids")
else False
)
company = (
self.browse(int(company_id.split(",")[0])).sudo()
if company_id and self.browse(int(company_id.split(",")[0])).sudo().favicon
else False
)
if company:
sha = hashlib.sha512(str(company.write_date).encode("utf-8")).hexdigest()[
:7
]
return f"/web/image/{self._name}/{company_id}/favicon?unique={sha}"
else:
return False

View File

@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

@ -0,0 +1,15 @@
Upload your favicon (16x16, 32x32, 64x64 or "as big as possible") on the
company form. The file format would be ico, gif or png with 16x16, 32x32 or
64x64 pixels and 16 colors. Highers resolutions or colors support depends on
the used browser, but most modern browsers do.
Note that most browsers cache favicons basically forever, so if you want your
icon to show up, you'll most probably have to delete you browser cache.
Some browsers can refresh the favicon, accessing the URL
<base_url>/web_favicon/favicon.
You have a sample SVG that can be used as template for generating your icon
in /static/src/img/master_original_favicon.svg. You can also search for some
favicon generators across the web.
To allow a user to edit the favicon it has to be member of group "Administration / Settings".

View File

@ -0,0 +1,2 @@
* OERP Canada \<<https://www.oerp.ca/>\>:
- Daryl Chen \<<dc@oerp.ca>\>

View File

@ -0,0 +1,10 @@
This module was written to allow you to customize your Odoo instance's shortcut
icon (aka favicon). This is useful for branding purposes, but also for
integrators who have many different Odoo instances running and need to see at a
glance which browser tab does what.
The icon is shown also for portal users when the website modules are not
installed.
More info about favicon: https://en.wikipedia.org/wiki/Favicon

View File

@ -0,0 +1,6 @@
* Allow to upload some big icon (preferrably SVG or the like) and generate
all the icons from it
* Generate icons suitable for mobile devices and web apps (see /static/src/img/
folder inside the module for a sample of the possible current formats.
* Put the icon definition at system level, not at company level. It doesn't
make sense (as the icon is cached) to have a different icon per company.

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,466 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Custom shortcut icon</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="custom-shortcut-icon">
<h1 class="title">Custom shortcut icon</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:4af1c92721d131728f92364370ba5145f45bac9b8e4d4396572737b9ccacd56e
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/OCA/web/tree/17.0/web_favicon"><img alt="OCA/web" src="https://img.shields.io/badge/github-OCA%2Fweb-lightgray.png?logo=github" /></a> <a class="reference external image-reference" href="https://translation.odoo-community.org/projects/web-17-0/web-17-0-web_favicon"><img alt="Translate me on Weblate" src="https://img.shields.io/badge/weblate-Translate%20me-F47D42.png" /></a> <a class="reference external image-reference" href="https://runboat.odoo-community.org/builds?repo=OCA/web&amp;target_branch=17.0"><img alt="Try me on Runboat" src="https://img.shields.io/badge/runboat-Try%20me-875A7B.png" /></a></p>
<p>This module was written to allow you to customize your Odoo instances
shortcut icon (aka favicon). This is useful for branding purposes, but
also for integrators who have many different Odoo instances running and
need to see at a glance which browser tab does what.</p>
<p>The icon is shown also for portal users when the website modules are not
installed.</p>
<p>More info about favicon: <a class="reference external" href="https://en.wikipedia.org/wiki/Favicon">https://en.wikipedia.org/wiki/Favicon</a></p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#configuration" id="toc-entry-1">Configuration</a></li>
<li><a class="reference internal" href="#known-issues-roadmap" id="toc-entry-2">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-3">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-4">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-5">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-6">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-7">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#toc-entry-1">Configuration</a></h1>
<p>Upload your favicon (16x16, 32x32, 64x64 or “as big as possible”) on the
company form. The file format would be ico, gif or png with 16x16, 32x32
or 64x64 pixels and 16 colors. Highers resolutions or colors support
depends on the used browser, but most modern browsers do.</p>
<p>Note that most browsers cache favicons basically forever, so if you want
your icon to show up, youll most probably have to delete you browser
cache. Some browsers can refresh the favicon, accessing the URL
&lt;base_url&gt;/web_favicon/favicon.</p>
<p>You have a sample SVG that can be used as template for generating your
icon in /static/src/img/master_original_favicon.svg. You can also search
for some favicon generators across the web.</p>
<p>To allow a user to edit the favicon it has to be member of group
“Administration / Settings”.</p>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#toc-entry-2">Known issues / Roadmap</a></h1>
<ul class="simple">
<li>Allow to upload some big icon (preferrably SVG or the like) and
generate all the icons from it</li>
<li>Generate icons suitable for mobile devices and web apps (see
/static/src/img/ folder inside the module for a sample of the
possible current formats.</li>
<li>Put the icon definition at system level, not at company level. It
doesnt make sense (as the icon is cached) to have a different icon
per company.</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#toc-entry-3">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/OCA/web/issues">GitHub Issues</a>.
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
<a class="reference external" href="https://github.com/OCA/web/issues/new?body=module:%20web_favicon%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#toc-entry-4">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#toc-entry-5">Authors</a></h2>
<ul class="simple">
<li>Therp BV</li>
<li>Tecnativa</li>
<li>OERP Canada</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#toc-entry-6">Contributors</a></h2>
<ul class="simple">
<li>OERP Canada &lt;<a class="reference external" href="https://www.oerp.ca/">https://www.oerp.ca/</a>&gt;:<ul>
<li>Daryl Chen &lt;<a class="reference external" href="mailto:dc&#64;oerp.ca">dc&#64;oerp.ca</a>&gt;</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#toc-entry-7">Maintainers</a></h2>
<p>This module is maintained by the OCA.</p>
<a class="reference external image-reference" href="https://odoo-community.org">
<img alt="Odoo Community Association" src="https://odoo-community.org/logo.png" />
</a>
<p>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.</p>
<p>This module is part of the <a class="reference external" href="https://github.com/OCA/web/tree/17.0/web_favicon">OCA/web</a> project on GitHub.</p>
<p>You are welcome to contribute. To learn how please visit <a class="reference external" href="https://odoo-community.org/page/Contribute">https://odoo-community.org/page/Contribute</a>.</p>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import test_web_favicon

View File

@ -0,0 +1,48 @@
# Copyright 2024 OERP Canada <https://www.oerp.ca>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
from PIL import Image
from odoo.tests import tagged
from odoo.tests.common import TransactionCase
from odoo.tools import base64_to_image, image_to_base64
from odoo.addons.website.tools import MockRequest
@tagged("post_install", "-at_install")
class TestWebFavicon(TransactionCase):
def test_01_web_favicon(self):
"""The goal of this test is to make sure the favicon is correctly
handled on the backend."""
# Test setting an Ico file directly, done through create
Company = self.env["res.company"]
company = Company.create(
{
"name": "Test Company",
"favicon": Company._get_default_favicon(),
}
)
image = base64_to_image(company.favicon)
self.assertEqual(image.format, "ICO")
# Test setting a JPEG file that is too big, done through write
bg_color = (135, 90, 123)
image = Image.new("RGB", (1920, 1080), color=bg_color)
company.favicon = image_to_base64(image, "JPEG")
image = base64_to_image(company.favicon)
self.assertEqual(image.format, "JPEG")
self.assertEqual(image.size, (1920, 1080))
self.assertEqual(image.getpixel((0, 0)), bg_color)
with MockRequest(self.env) as mock_request:
mock_request.httprequest.cookies = {"cids": str(company.id)}
self.assertTrue(Company._get_favicon())
def test_02_default_favicon_creation(self):
"""Test if default favicon is set when creating a company without favicon."""
Company = self.env["res.company"]
company = Company.create({"name": "Test Company"})
self.assertTrue(company.favicon, "Default favicon not set on company creation.")

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2024 OERP Canada <https://www.oerp.ca>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<data noupdate="1">
<record id="base.main_company" model="res.company">
<field
name="favicon"
model="res.company"
eval="obj()._get_default_favicon(original=True)"
/>
</record>
</data>
<record id="view_company_form_inherit" model="ir.ui.view">
<field name="name">res.company.form.inherit</field>
<field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form" />
<field name="arch" type="xml">
<xpath expr="//field[@name='color']" position="after">
<field
name="favicon"
widget="image"
class="float-start oe_avatar"
groups="base.group_no_one"
/>
</xpath>
</field>
</record>
</odoo>

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright 2024 OERP Canada <https://www.oerp.ca>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -->
<odoo>
<template id="favicon_icon" inherit_id="web.layout" name="Web layout">
<xpath expr="//head/link[@rel='shortcut icon']" position="attributes">
<attribute
name="t-att-href"
>env['res.company'].sudo()._get_favicon() or '/web/static/img/favicon.ico'</attribute>
</xpath>
</template>
</odoo>