From 0c7a54f1396f5d3e51985cb3de6be114095e4f74 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#122398 X-original-commit: be5032058cfa944a252af2509c7fa8807d01861e Signed-off-by: Romain Derie (rde) <rde@odoo.com> --- 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 7777a0d29430..1a65b239b15d 100644 --- a/addons/website/i18n/website.pot +++ b/addons/website/i18n/website.pot @@ -9405,6 +9405,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 a45384499483..ab17d894e4d3 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); _.times(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)'; } @@ -157,6 +170,15 @@ const FontFamilyPickerUserValueWidget = SelectUserValueWidget.extend({ fontEl.dataset[methodName] = fontKey; fontEl.dataset.font = realFontNb; 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); }); @@ -261,6 +283,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 { @@ -305,7 +341,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 46b47bde4646..c43f5e603824 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 b0dbafcc725c..5e6dfdcdd154 100644 --- a/addons/website/static/src/xml/website.editor.xml +++ b/addons/website/static/src/xml/website.editor.xml @@ -69,10 +69,10 @@ </div> </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 me-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 ms-2 fa fa-trash-o o_we_delete_google_font_btn" + class="text-danger fa fa-trash-o o_we_delete_google_font_btn" t-att-aria-label="delete_font_title" t-att-title="delete_font_title" t-att-data-local-font="local" -- GitLab