From 5764c74232fa8af1c7de7bb37a2f8c5f165d8d14 Mon Sep 17 00:00:00 2001 From: Antoine Guenet Date: Tue, 26 Apr 2022 12:16:05 +0000 Subject: [PATCH] [FIX] mass_mailing: get styles for design tab from DOM Before this commit, the design tab retrieved the current styles exclusively from the `#design-element` style element. This meant that if a template included that element to define its own styles, the defaults were lost for the styles that it didn't define. This reads the styles from the DOM instead so this is never an issue. In order for the design tab to have values to read, we initialized the `#design-tab` element with the css of the page. This was a temporary workaround. Now that values are read via `getComputedStyle`, we don't need it anymore. task-2833420 closes odoo/odoo#89745 X-original-commit: e8f2f71f76f86bae84253374935fd7d14428746d Signed-off-by: David Monjoie (dmo) --- .../src/js/mass_mailing_design_constants.js | 65 ++----------------- .../static/src/js/mass_mailing_snippets.js | 39 +++++++++-- 2 files changed, 36 insertions(+), 68 deletions(-) diff --git a/addons/mass_mailing/static/src/js/mass_mailing_design_constants.js b/addons/mass_mailing/static/src/js/mass_mailing_design_constants.js index 1ddcf17cb4a..3b7d5f838a4 100644 --- a/addons/mass_mailing/static/src/js/mass_mailing_design_constants.js +++ b/addons/mass_mailing/static/src/js/mass_mailing_design_constants.js @@ -1,71 +1,15 @@ /** @odoo-module alias=mass_mailing.design_constants**/ export const CSS_PREFIX = '.o_mail_wrapper'; -export const DEFAULT_CSS_OBJECT = { - h1: { - 'font-size': '35px', - color: '#212529', - 'font-family': 'Arial,Helvetica Neue,Helvetica,sans-serif', - }, - h2: { - 'font-size': '28px', - color: '#212529', - 'font-family': 'Arial,Helvetica Neue,Helvetica,sans-serif', - }, - h3: { - 'font-size': '24.5px', - color: '#212529', - 'font-family': 'Arial,Helvetica Neue,Helvetica,sans-serif', - }, - 'p, p > *, li, li > *': { - 'font-size': '14px', - color: '#212529', - 'font-family': 'Arial,Helvetica Neue,Helvetica,sans-serif', - }, - 'a:not(.btn), a.btn-link': { - 'text-decoration-line': 'none', - color: '#276e72', - }, - 'a.btn-primary, a.btn-outline-primary, a.btn-fill-primary': { - 'font-size': '12.25px', - color: '#FFFFFF', - 'background-color': '#35979c', - 'border-color': '#35979c', - 'border-style': 'solid', - 'border-width': '1px', - }, - 'a.btn-secondary, a.btn-outline-secondary, a.btn-fill-secondary': { - 'font-size': '12.25px', - color: '#FFFFFF', - 'background-color': '#685563', - 'border-color': '#685563', - 'border-style': 'solid', - 'border-width': '1px', - }, - hr: { - 'border-top-color': '#212529', - 'border-top-style': 'solid', - 'border-top-width': '1px', - width: '100%', - } -}; -export const DEFAULT_CSS = Object.keys(DEFAULT_CSS_OBJECT).map( // selectors - key => key.split(',').map( // each individual comma separated selector - selector => `${CSS_PREFIX} ${selector.trim()} {\n ${ // selector { - Object.keys(DEFAULT_CSS_OBJECT[key]).map( // css properties - prop => `${prop}: ${DEFAULT_CSS_OBJECT[key][prop]}`) // [prop: value] - .join(';\n ')}\n}` // prop: value; - ).join('\n') -).join('\n'); // css text export const BTN_SIZE_STYLES = { 'btn-sm': { - 'padding': '0.25rem 0.5rem', + 'padding': '3px 7.5px', 'font-size': '0.875rem', 'line-height': '1.5rem', }, 'btn-lg': { - 'padding': '0.5rem 1rem', + 'padding': '7px 14px', 'font-size': '1.25rem', 'line-height': '1.5rem', }, @@ -126,7 +70,6 @@ export const initializeDesignTabCss = $editable => { // The style element needs to be within the layout of the email in // order to be saved along with it. $editable.find('.o_layout').prepend(styleElement); - styleElement.textContent = splitCss(DEFAULT_CSS); } }; @@ -143,7 +86,7 @@ export const FONT_FAMILIES = [ ].map(fontFamily => normalizeFontFamily(fontFamily)); export default { - CSS_PREFIX, DEFAULT_CSS_OBJECT, DEFAULT_CSS, BTN_SIZE_STYLES, - DEFAULT_BUTTON_SIZE, PRIORITY_STYLES, RE_CSS_TEXT_MATCH, FONT_FAMILIES, + CSS_PREFIX, BTN_SIZE_STYLES, DEFAULT_BUTTON_SIZE, PRIORITY_STYLES, + RE_CSS_TEXT_MATCH, FONT_FAMILIES, splitCss, getFontName, normalizeFontFamily, initializeDesignTabCss, } diff --git a/addons/mass_mailing/static/src/js/mass_mailing_snippets.js b/addons/mass_mailing/static/src/js/mass_mailing_snippets.js index 888cbc3e837..afcec4e4bad 100644 --- a/addons/mass_mailing/static/src/js/mass_mailing_snippets.js +++ b/addons/mass_mailing/static/src/js/mass_mailing_snippets.js @@ -185,6 +185,7 @@ options.registry.DesignTab = options.Class.extend({ const res = await this._super(...arguments); const $editable = this.options.wysiwyg.getEditable(); this.document = $editable[0].ownerDocument; + this.$layout = $editable.find('.o_layout'); initializeDesignTabCss($editable); this.styleElement = this.document.querySelector('#design-element'); // When editing a stylesheet, its content is not updated so it won't be @@ -319,18 +320,42 @@ options.registry.DesignTab = options.Class.extend({ const res = await this._super(...arguments); if (res === undefined) { switch (methodName) { + case 'applyButtonSize': case 'customizeCssProperty': { if (!params.selectorText) { return; } - const rule = this._getRule(this._getSelectors(params.selectorText)[0]); - if (params.possibleValues && params.possibleValues[1] === FONT_FAMILIES[0]) { - // For font-family, we need to normalize it so it - // matches an option value. - return rule && normalizeFontFamily(rule.style.getPropertyValue('font-family')); - } else { - return rule && rule.style.getPropertyValue(params.cssProperty); + // Here we parse the selector in order to create a matching + // element that we inject into the DOM so we can retrieve + // its computed style. We then remove the element from the + // DOM, no harm, no foul. + const firstSelector = params.selectorText.split(',')[0].replace(CSS_PREFIX, '').trim(); + const classes = firstSelector.replace(/:not\([^\)]*\)/g, '').match(/\.([\w\d-_]+)/g) || []; + const fakeElement = document.createElement(firstSelector.split(/[\.:, ]/)[0]); + for (const className of classes) { + fakeElement.classList.toggle(className.replace('.', ''), true); } + this.$layout.find(CSS_PREFIX).prepend(fakeElement); + let res; + if (methodName === 'applyButtonSize') { + // Match a button size by its padding value. + const padding = getComputedStyle(fakeElement).padding; + const classIndex = Object.values(BTN_SIZE_STYLES).findIndex(style => style.padding === padding); + res = classIndex >= 0 ? Object.keys(BTN_SIZE_STYLES)[classIndex] : DEFAULT_BUTTON_SIZE; + } else { + fakeElement.style.display = 'none'; // Needed to get width in %. + res = getComputedStyle(fakeElement)[params.cssProperty || 'font-family']; + if (params.possibleValues && params.possibleValues[1] === FONT_FAMILIES[0]) { + // For font-family, we need to normalize it so it + // matches an option value. + res = normalizeFontFamily(res); + } + if (params.cssProperty === 'font-weight') { + res = parseInt(res) >= 600 ? 'bolder' : ''; + } + } + fakeElement.remove(); + return res; } case 'applyButtonSize': // Match a button size by its padding value.