[IMP] base, mail: split company email colors from document colors
PURPOSE Settings allow to change colors used in emails (primary and secondary colors). Those are used for headers and buttons. They are currently shared with colors used for documents and reporting: changing email colors change documents colors, which is not expected nor clearly indicated. SPECIFICATIONS Split configuration: colors used in documents may differ from colors used in emails. Duplicate color fields (primary and secondary). To ease setup when updating documents colors, update mail colors accordingly. Inverse is not true as we consider documents being the main configuration, and emails a more fine-grain configuration. Task-3346388 closes odoo/odoo#123678 Related: odoo/upgrade#4735 Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.mail.tests.test_notify_security_update import TestNotifySecurityUpdate
|
||||
from odoo.addons.mail.tests.test_security import TestNotifySecurityUpdate
|
||||
from odoo.tests import users
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from . import common
|
||||
from . import test_assetsbundle
|
||||
from . import test_health
|
||||
from . import test_ir_model
|
||||
from . import test_ir_websocket
|
||||
from . import test_websocket_caryall
|
||||
from . import test_websocket_controller
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=no;"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE" />
|
||||
<style type="text/css">
|
||||
<t t-set="color_company" t-value="company.secondary_color or '#875a7b'"/>
|
||||
<t t-set="color_company" t-value="company.email_secondary_color or '#875a7b'"/>
|
||||
/* Remove space around the email design. */
|
||||
html,
|
||||
body {
|
||||
@@ -360,7 +360,7 @@
|
||||
<t t-set="kpi_subtitle" t-value="kpi_info['kpi_col1']['col_subtitle']" />
|
||||
</div>
|
||||
</td>
|
||||
<td t-if="kpi_info.get('kpi_col2')" class="kpi_cell" t-att-style="'border-top: 2px solid ' + (company.secondary_color or '#875a7b')">
|
||||
<td t-if="kpi_info.get('kpi_col2')" class="kpi_cell" t-att-style="'border-top: 2px solid ' + (company.email_secondary_color or '#875a7b')">
|
||||
<div t-call="digest.digest_tool_kpi">
|
||||
<t t-set="kpi_value" t-value="kpi_info['kpi_col2']['value']" />
|
||||
<t t-set="kpi_margin" t-value="kpi_info['kpi_col2'].get('margin')" />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
{
|
||||
'name': 'Discuss',
|
||||
'version': '1.13',
|
||||
'version': '1.14',
|
||||
'category': 'Productivity/Discuss',
|
||||
'sequence': 145,
|
||||
'summary': 'Chat, mail gateway and private channels',
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
<table cellspacing="0" cellpadding="0" border="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td t-if="has_button_access" t-att-style="'border-radius: 3px; text-align: center; background: ' + (company.secondary_color if company.secondary_color else '#875A7B')">
|
||||
<td t-if="has_button_access" t-att-style="'border-radius: 3px; text-align: center; background: ' + (company.email_secondary_color or '#875A7B') + ';'">
|
||||
<a t-att-href="button_access['url']" style="font-size: 12px; color: #FFFFFF; display: block; padding: 8px 12px 11px; text-decoration: none !important; font-weight: 400;">
|
||||
<t t-out="button_access['title']"/>
|
||||
</a>
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
<td t-if="actions">
|
||||
<t t-foreach="actions" t-as="action">
|
||||
<a t-att-href="action['url']" t-att-style="'font-size: 12px; color: ' + (company.secondary_color or '#875A7B')+ '; text-decoration:none !important;'">
|
||||
<a t-att-href="action['url']" t-att-style="'font-size: 12px; color: ' + (company.email_secondary_color or '#875A7B')+ '; text-decoration:none !important;'">
|
||||
<t t-out="action['title']"/>
|
||||
</a>
|
||||
&nbsp;&nbsp;
|
||||
@@ -101,7 +101,8 @@
|
||||
</p>
|
||||
</div>
|
||||
<div style="color: #555555; font-size:11px;">
|
||||
Powered by <a target="_blank" href="https://www.odoo.com?utm_source=db&utm_medium=email" style="color: #875A7B;">Odoo</a>
|
||||
Powered by <a target="_blank" href="https://www.odoo.com?utm_source=db&utm_medium=email"
|
||||
t-att-style="'color: ' + (company.email_secondary_color or '#875A7B') + ';'">Odoo</a>
|
||||
<span id="mail_unfollow">
|
||||
| <a href="/mail/unfollow" style="text-decoration:none; color:#555555;">Unfollow</a>
|
||||
</span>
|
||||
@@ -174,7 +175,8 @@
|
||||
</td></tr>
|
||||
<!-- POWERED BY -->
|
||||
<tr><td align="center" style="min-width: 590px;">
|
||||
Powered by <a target="_blank" href="https://www.odoo.com?utm_source=db&utm_medium=email" style="color: #875A7B;">Odoo</a>
|
||||
Powered by <a target="_blank" href="https://www.odoo.com?utm_source=db&utm_medium=email"
|
||||
t-att-style="'color: ' + (company.email_secondary_color or '#875A7B') + ';'">Odoo</a>
|
||||
<span id="mail_unfollow">
|
||||
| <a href="/mail/unfollow" style="text-decoration:none; color:#555555;">Unfollow</a>
|
||||
</span>
|
||||
|
||||
@@ -12,8 +12,15 @@ class Company(models.Model):
|
||||
catchall_formatted = fields.Char(string="Catchall", compute="_compute_catchall")
|
||||
# the compute method is sudo'ed because it needs to access res.partner records
|
||||
# portal users cannot access those (but they should be able to read the company email address)
|
||||
email_formatted = fields.Char(string="Formatted Email",
|
||||
email_formatted = fields.Char(
|
||||
string="Formatted Email",
|
||||
compute="_compute_email_formatted", compute_sudo=True)
|
||||
email_primary_color = fields.Char(
|
||||
"Email Header Color", compute="_compute_email_primary_color",
|
||||
readonly=False, store=True)
|
||||
email_secondary_color = fields.Char(
|
||||
"Email Button Color", compute="_compute_email_secondary_color",
|
||||
readonly=False, store=True)
|
||||
|
||||
@api.depends('name')
|
||||
def _compute_catchall(self):
|
||||
@@ -38,3 +45,21 @@ class Company(models.Model):
|
||||
company.email_formatted = company.catchall_formatted
|
||||
else:
|
||||
company.email_formatted = ''
|
||||
|
||||
@api.depends('primary_color')
|
||||
def _compute_email_primary_color(self):
|
||||
""" When updating documents layout colors, force usage of same colors
|
||||
for emails as it is considered as base colors for all communication.
|
||||
Inverse is not true, people may change email colors without changing
|
||||
their overall layout. """
|
||||
for company in self:
|
||||
company.email_primary_color = company.primary_color or '#000000'
|
||||
|
||||
@api.depends('secondary_color')
|
||||
def _compute_email_secondary_color(self):
|
||||
""" When updating documents layout colors, force usage of same colors
|
||||
for emails as it is considered as base colors for all communication.
|
||||
Inverse is not true, people may change email colors without changing
|
||||
their overall layout. """
|
||||
for company in self:
|
||||
company.email_secondary_color = company.secondary_color or '#875A7B'
|
||||
|
||||
@@ -36,8 +36,8 @@ class ResConfigSettings(models.TransientModel):
|
||||
'Twilio Account Auth Token',
|
||||
config_parameter='mail.twilio_account_token',
|
||||
)
|
||||
primary_color = fields.Char(related='company_id.primary_color', string="Header Color", readonly=False)
|
||||
secondary_color = fields.Char(related='company_id.secondary_color', string="Button Color", readonly=False)
|
||||
email_primary_color = fields.Char(related='company_id.email_primary_color', readonly=False)
|
||||
email_secondary_color = fields.Char(related='company_id.email_secondary_color', readonly=False)
|
||||
|
||||
tenor_api_key = fields.Char(
|
||||
'Tenor API key',
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import test_get_model_definitions
|
||||
from . import test_link_preview
|
||||
from . import test_mail_chatter_reload
|
||||
from . import test_mail_activity
|
||||
from . import test_mail_composer
|
||||
from . import test_mail_full_composer
|
||||
from . import test_mail_render
|
||||
from . import test_mail_template
|
||||
from . import test_mail_tools
|
||||
from . import test_notify_security_update
|
||||
from . import test_res_company
|
||||
from . import test_res_partner
|
||||
from . import test_res_users
|
||||
from . import test_res_users_settings
|
||||
from . import test_security
|
||||
from . import test_uninstall
|
||||
from . import test_update_notification
|
||||
from . import test_user_modify_own_profile
|
||||
|
||||
from .discuss import *
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ from odoo.tests.common import tagged, HttpCase
|
||||
|
||||
|
||||
@tagged("-at_install", "post_install")
|
||||
class TestMailChatterReload(HttpCase):
|
||||
class TestMailActivityChatter(HttpCase):
|
||||
|
||||
def test_chatter_activity_tour(self):
|
||||
testuser = self.env['res.users'].create({
|
||||
@@ -0,0 +1,52 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.addons.mail.tests.common import MailCommon
|
||||
from odoo.tests.common import tagged, users
|
||||
|
||||
|
||||
@tagged('res_company')
|
||||
class TestCompany(MailCommon):
|
||||
|
||||
@users('admin')
|
||||
def test_company_colors(self):
|
||||
""" Test primary and secondary color management, especially the choice
|
||||
between document colors and email-specific colors. When setting document
|
||||
layout colors, email colors are updated. When updating email colors
|
||||
layout is not updated, they are less important. """
|
||||
# propagate at create
|
||||
new_company = self.env['res.company'].create({
|
||||
'name': 'Test Colors',
|
||||
'primary_color': '#AAAAAA',
|
||||
'secondary_color': '#BBBBBB',
|
||||
})
|
||||
self.assertEqual(new_company.primary_color, '#AAAAAA')
|
||||
self.assertEqual(new_company.secondary_color, '#BBBBBB')
|
||||
self.assertEqual(new_company.email_primary_color, '#AAAAAA',
|
||||
'Updating document colors changes email colors')
|
||||
self.assertEqual(new_company.email_secondary_color, '#BBBBBB',
|
||||
'Updating document colors changes email colors')
|
||||
|
||||
# email can be changed independently
|
||||
new_company.write({
|
||||
'email_primary_color': '#CCCCCC',
|
||||
'email_secondary_color': '#DDDDDD',
|
||||
})
|
||||
self.assertEqual(new_company.primary_color, '#AAAAAA',
|
||||
'Updating email colors does not change global layout')
|
||||
self.assertEqual(new_company.secondary_color, '#BBBBBB',
|
||||
'Updating email colors does not change global layout')
|
||||
self.assertEqual(new_company.email_primary_color, '#CCCCCC')
|
||||
self.assertEqual(new_company.email_secondary_color, '#DDDDDD')
|
||||
|
||||
# reset document -> reset email
|
||||
new_company.write({
|
||||
'primary_color': '#EEEEEE',
|
||||
'secondary_color': '#FFFFFF',
|
||||
})
|
||||
self.assertEqual(new_company.primary_color, '#EEEEEE')
|
||||
self.assertEqual(new_company.secondary_color, '#FFFFFF')
|
||||
self.assertEqual(new_company.email_primary_color, '#EEEEEE',
|
||||
'Updating document colors changes email colors')
|
||||
self.assertEqual(new_company.email_secondary_color, '#FFFFFF',
|
||||
'Updating document colors changes email colors')
|
||||
@@ -2,9 +2,12 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from psycopg2 import IntegrityError
|
||||
from unittest.mock import patch
|
||||
|
||||
from odoo import Command
|
||||
from odoo.addons.base.models.res_users import Users
|
||||
from odoo.addons.mail.tests.common import MailCommon, mail_new_test_user
|
||||
from odoo.tests import HttpCase, tagged
|
||||
from odoo.tools import mute_logger
|
||||
|
||||
|
||||
@@ -45,3 +48,21 @@ class TestUser(MailCommon):
|
||||
]})
|
||||
self.assertEqual(user.notification_type, 'email')
|
||||
self.assertNotIn(self.env.ref('mail.group_mail_notification_type_inbox'), user.groups_id)
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestUserModifyOwnProfile(HttpCase):
|
||||
|
||||
def test_user_modify_own_profile(self):
|
||||
"""" A user should be able to modify their own profile.
|
||||
Even if that user does not have access rights to write on the res.users model. """
|
||||
|
||||
# avoid 'reload_context' action in the middle of the tour to ease steps and form save checks
|
||||
with patch.object(Users, 'preference_save', lambda self: True):
|
||||
self.start_tour(
|
||||
"/web",
|
||||
"mail/static/tests/tours/user_modify_own_profile_tour.js",
|
||||
login="demo",
|
||||
step_delay=100,
|
||||
)
|
||||
self.assertEqual(self.env.ref('base.user_demo').email, "updatedemail@example.com")
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo.tests import HttpCase, tagged
|
||||
from odoo.addons.base.models.res_users import Users
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
@tagged('-at_install', 'post_install')
|
||||
class TestUserModifyOwnProfile(HttpCase):
|
||||
|
||||
def test_user_modify_own_profile(self):
|
||||
"""" A user should be able to modify their own profile.
|
||||
Even if that user does not have access rights to write on the res.users model. """
|
||||
|
||||
# avoid 'reload_context' action in the middle of the tour to ease steps and form save checks
|
||||
with patch.object(Users, 'preference_save', lambda self: True):
|
||||
self.start_tour("/web", "mail/static/tests/tours/user_modify_own_profile_tour.js", login="demo", step_delay=100)
|
||||
self.assertEqual(self.env.ref('base.user_demo').email, "updatedemail@example.com")
|
||||
@@ -92,11 +92,11 @@
|
||||
<setting string="Email Templates" help="Customize the look and feel of automated emails" id="mail_templates_setting" groups="mail.group_mail_template_editor,base.group_system">
|
||||
<div class="w-50 row">
|
||||
<span class="d-block w-75 py-2">Header Color</span>
|
||||
<field name="primary_color" class="d-block w-25 p-0 m-0" widget="color"/>
|
||||
<field name="email_primary_color" class="d-block w-25 p-0 m-0" widget="color"/>
|
||||
</div>
|
||||
<div class="w-50 row mt-1">
|
||||
<span class="d-block w-75 py-2">Button Color</span>
|
||||
<field name="secondary_color" class="d-block w-25 p-0 m-0" widget="color"/>
|
||||
<field name="email_secondary_color" class="d-block w-25 p-0 m-0" widget="color"/>
|
||||
</div>
|
||||
<button name="open_email_layout" icon="oi-arrow-right"
|
||||
type="object" string="Update Mail Layout"
|
||||
|
||||
@@ -162,7 +162,7 @@
|
||||
<tr>
|
||||
<td style="margin: 0; padding:0;">
|
||||
<table cellspacing="0" cellpadding="0" border="0" align="center" style="width:100%; border-collapse: collapse;">
|
||||
<tr t-att-style="'color: ' + (company.secondary_color or '#875a7b') + '; font-size: 16px; font-weight: 500;'">
|
||||
<tr t-att-style="'color: ' + (company.email_secondary_color or '#875a7b') + '; font-size: 16px; font-weight: 500;'">
|
||||
<td style="width: 70%;padding: 10px 0; text-align: center; border: 1px solid #e7e7e7;">Button Label</td>
|
||||
<td style="width: 30%;padding: 10px 0; text-align: center; border: 1px solid #e7e7e7;">%Click (Total)</td>
|
||||
</tr>
|
||||
|
||||
Reference in New Issue
Block a user