From 5fd185ef8513e49c0afdb1ba0002f3e32cfdd896 Mon Sep 17 00:00:00 2001 From: Benjamin Vray 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#122652 X-original-commit: 948ff01e64e5d71d60d209d074dd6be6510fe794 Signed-off-by: Romain Derie (rde) --- addons/website/i18n/website.pot | 9 ++++ .../static/src/js/editor/snippets.options.js | 41 ++++++++++++++++++- .../static/src/scss/secondary_variables.scss | 3 ++ .../website/static/src/xml/website.editor.xml | 4 +- 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/addons/website/i18n/website.pot b/addons/website/i18n/website.pot index 833a3cdd710..9a28d8f92f5 100644 --- a/addons/website/i18n/website.pot +++ b/addons/website/i18n/website.pot @@ -9430,6 +9430,15 @@ msgid "" " Useful to (soft) reset a broken view." msgstr "" +#. module: website +#. odoo-javascript +#: 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 #. odoo-javascript #: code:addons/website/static/src/xml/website.editor.xml:0 diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index 60f40e714a3..18e66dff155 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -112,12 +112,22 @@ const FontFamilyPickerUserValueWidget = SelectUserValueWidget.extend({ start: async function () { const style = window.getComputedStyle(this.$target[0].ownerDocument.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); @@ -140,12 +150,15 @@ const FontFamilyPickerUserValueWidget = SelectUserValueWidget.extend({ const fontEls = []; const methodName = this.el.dataset.methodName || 'customizeWebsiteVariable'; const variable = this.el.dataset.variable; + const themeFontsNb = nbFonts - (this.googleLocalFonts.length + this.googleFonts.length); for (let fontNb = 0; fontNb < nbFonts; fontNb++) { const realFontNb = fontNb + 1; const fontKey = weUtils.getCSSVariableValue(`font-number-${realFontNb}`, style); + this.allFonts.push(fontKey); let fontName = fontKey.slice(1, -1); // Unquote let fontFamily = fontName; - if (fontName === "SYSTEM_FONTS") { + const isSystemFonts = fontName === "SYSTEM_FONTS"; + if (isSystemFonts) { fontName = _t("System Fonts"); fontFamily = 'var(--o-system-fonts)'; } @@ -154,6 +167,15 @@ const FontFamilyPickerUserValueWidget = SelectUserValueWidget.extend({ fontEl.dataset.variable = variable; fontEl.dataset[methodName] = fontKey; fontEl.dataset.fontFamily = fontFamily; + if ((realFontNb <= themeFontsNb) && !isSystemFonts) { + // 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 me-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); }; @@ -251,6 +273,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 { @@ -295,7 +331,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 46b47bde464..c43f5e60382 100644 --- a/addons/website/static/src/scss/secondary_variables.scss +++ b/addons/website/static/src/scss/secondary_variables.scss @@ -233,6 +233,9 @@ $o-theme-font-configs: map-merge($o-base-theme-font-configs, $o-theme-font-confi // 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 a6b3abb345a..ca63e9bcb6a 100644 --- a/addons/website/static/src/xml/website.editor.xml +++ b/addons/website/static/src/xml/website.editor.xml @@ -69,10 +69,10 @@ - + Delete this font