From be5032058cfa944a252af2509c7fa8807d01861e Mon Sep 17 00:00:00 2001 From: Benjamin Vray <bvr@odoo.com> Date: Tue, 25 Oct 2022 08:08:28 +0000 Subject: [PATCH] [FIX] website: fix adding same font family twice Steps to reproduce the bug : - Add the same google font twice with the font family selector in the option tab of the editor panel. - The font will be displayed only once in the font selector menu but 2 trash icons will be added, one for the added font and one for the font that was already there. This commit fix this and allows now the user to add the same font twice, but only to replace a served font by a local font. The opposite does not make sense, but if the user really wants to replace a local font with a served, it is always possible by deleting the locale beforehand. In addition, this commit adds a cloud icon next to the default fonts of the theme. Since these fonts are served by Google, it is logical to have the cloud icon. This is consistent with the cloud icon that is present when the user adds a font served by Google. task-2998689 closes odoo/odoo#103402 Signed-off-by: Romain Derie (rde) <rde@odoo.com> --- addons/website/i18n/website.pot | 10 +++++ .../static/src/js/editor/snippets.options.js | 40 ++++++++++++++++++- .../static/src/scss/secondary_variables.scss | 3 ++ .../website/static/src/xml/website.editor.xml | 2 +- 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/addons/website/i18n/website.pot b/addons/website/i18n/website.pot index 891c277be713..8915466845dd 100644 --- a/addons/website/i18n/website.pot +++ b/addons/website/i18n/website.pot @@ -7195,6 +7195,16 @@ msgstr "" #. module: website #. openerp-web +#: code:addons/website/static/src/js/editor/snippets.options.js:0 +#, python-format +msgid "" +"This font already exists, you can only add it as a local font to replace the" +" server version." +msgstr "" + +#. module: website +#. openerp-web +#: code:addons/website/static/src/js/editor/snippets.options.js:0 #: code:addons/website/static/src/xml/website.editor.xml:0 #, python-format msgid "This font is hosted and served to your visitors by Google servers" diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index 2c271c7e36e5..4cbd56592a45 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -91,25 +91,48 @@ const FontFamilyPickerUserValueWidget = SelectUserValueWidget.extend({ start: async function () { const style = window.getComputedStyle(document.documentElement); const nbFonts = parseInt(weUtils.getCSSVariableValue('number-of-fonts', style)); + // User fonts served by google server. const googleFontsProperty = weUtils.getCSSVariableValue('google-fonts', style); this.googleFonts = googleFontsProperty ? googleFontsProperty.split(/\s*,\s*/g) : []; this.googleFonts = this.googleFonts.map(font => font.substring(1, font.length - 1)); // Unquote + // Local user fonts. const googleLocalFontsProperty = weUtils.getCSSVariableValue('google-local-fonts', style); this.googleLocalFonts = googleLocalFontsProperty ? googleLocalFontsProperty.slice(1, -1).split(/\s*,\s*/g) : []; + // If a same font exists both remotely and locally, we remove the remote + // font to prioritize the local font. The remote one will never be + // displayed or loaded as long as the local one exists. + this.googleFonts = this.googleFonts.filter(font => { + const localFonts = this.googleLocalFonts.map(localFont => localFont.split(":")[0]); + return localFonts.indexOf(`'${font}'`) === -1; + }); + this.allFonts = []; await this._super(...arguments); const fontEls = []; const methodName = this.el.dataset.methodName || 'customizeWebsiteVariable'; const variable = this.el.dataset.variable; + const themeFontsNb = nbFonts - (this.googleLocalFonts.length + this.googleFonts.length); _.times(nbFonts, fontNb => { const realFontNb = fontNb + 1; const fontEl = document.createElement('we-button'); fontEl.classList.add(`o_we_option_font_${realFontNb}`); fontEl.dataset.variable = variable; fontEl.dataset[methodName] = weUtils.getCSSVariableValue(`font-number-${realFontNb}`, style); + const font = weUtils.getCSSVariableValue(`font-number-${realFontNb}`, style); + this.allFonts.push(font); + fontEl.dataset[methodName] = font; fontEl.dataset.font = realFontNb; + if (realFontNb <= themeFontsNb) { + // Add the "cloud" icon next to the theme's default fonts + // because they are served by Google. + fontEl.appendChild(Object.assign(document.createElement('i'), { + role: 'button', + className: 'text-info ml-2 fa fa-cloud', + title: _t("This font is hosted and served to your visitors by Google servers"), + })); + } fontEls.push(fontEl); this.menuEl.appendChild(fontEl); }); @@ -209,6 +232,20 @@ const FontFamilyPickerUserValueWidget = SelectUserValueWidget.extend({ const font = m[1].replace(/\+/g, ' '); const googleFontServe = dialog.el.querySelector('#google_font_serve').checked; + const fontName = `'${font}'`; + // If the font already exists, it will only be added if + // the user chooses to add it locally when it is already + // imported from the Google Fonts server. + const fontExistsLocally = this.googleLocalFonts.some(localFont => localFont.split(':')[0] === fontName); + const fontExistsOnServer = this.allFonts.includes(fontName); + const preventFontAddition = fontExistsLocally || (fontExistsOnServer && googleFontServe); + if (preventFontAddition) { + inputEl.classList.add('is-invalid'); + // Show custom validity error message. + inputEl.setCustomValidity(_t("This font already exists, you can only add it as a local font to replace the server version.")); + inputEl.reportValidity(); + return; + } if (googleFontServe) { this.googleFonts.push(font); } else { @@ -253,7 +290,8 @@ const FontFamilyPickerUserValueWidget = SelectUserValueWidget.extend({ let googleFontName; if (isLocalFont) { const googleFont = this.googleLocalFonts[googleFontIndex].split(':'); - googleFontName = googleFont[0]; + // Remove double quotes + googleFontName = googleFont[0].substring(1, googleFont[0].length - 1); values['delete-font-attachment-id'] = googleFont[1]; this.googleLocalFonts.splice(googleFontIndex, 1); } else { diff --git a/addons/website/static/src/scss/secondary_variables.scss b/addons/website/static/src/scss/secondary_variables.scss index 0f85a3fc94b7..967201554fb2 100644 --- a/addons/website/static/src/scss/secondary_variables.scss +++ b/addons/website/static/src/scss/secondary_variables.scss @@ -172,6 +172,9 @@ $o-we-auto-contrast-exclusions: join($o-we-auto-contrast-exclusions, map-keys(o- // Add locally hosted google fonts @each $font-name, $font-attach-id in (o-website-value('google-local-fonts') or ()) { + // If a font exists both remotely and locally, we remove the remote font to + // prioritize the local font. + $o-theme-font-configs: map-remove($o-theme-font-configs, $font-name); $o-theme-font-configs: map-merge($o-theme-font-configs, ( $font-name: ( 'family': (quote($font-name), sans-serif), diff --git a/addons/website/static/src/xml/website.editor.xml b/addons/website/static/src/xml/website.editor.xml index 571f84c659d0..c46aa1aa2d3e 100644 --- a/addons/website/static/src/xml/website.editor.xml +++ b/addons/website/static/src/xml/website.editor.xml @@ -78,7 +78,7 @@ <p>Adding a font requires a reload of the page. This will save all your changes.</p> </div> <t t-name="website.delete_google_font_btn"> - <i t-if="!local" role="button" class="text-info ms-2 fa fa-cloud" title="This font is hosted and served to your visitors by Google servers"/> + <i t-if="!local" role="button" class="text-info ml-2 fa fa-cloud" title="This font is hosted and served to your visitors by Google servers"/> <t t-set="delete_font_title">Delete this font</t> <i role="button" class="text-danger ml-2 fa fa-trash-o o_we_delete_google_font_btn" -- GitLab