mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Added custom fonts feature check (#21738)
ref DES-1011 - previously, we were hiding the old font settings from the official themes without checking if they support the custom fonts or not - now we use the gscan warning info to check this — only when there's support, we hide the settings which means users with the older version will get the old settings back - also added two new tests for this procedure
This commit is contained in:
parent
7c1d7080e9
commit
ea0e598bf2
7 changed files with 242 additions and 2 deletions
|
@ -52,6 +52,11 @@ export const useBrowseThemes = createQuery<ThemesResponseType>({
|
|||
path: '/themes/'
|
||||
});
|
||||
|
||||
export const useActiveTheme = createQuery<ThemesInstallResponseType>({
|
||||
dataType,
|
||||
path: '/themes/active/'
|
||||
});
|
||||
|
||||
export const useActivateTheme = createMutation<ThemesResponseType, string>({
|
||||
method: 'PUT',
|
||||
path: name => `/themes/${name}/activate/`,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import ThemeSetting from './ThemeSetting';
|
||||
import useCustomFonts from '../../../../hooks/useCustomFonts';
|
||||
import useFeatureFlag from '../../../../hooks/useFeatureFlag';
|
||||
import {CustomThemeSetting} from '@tryghost/admin-x-framework/api/customThemeSettings';
|
||||
import {Form} from '@tryghost/admin-x-design-system';
|
||||
|
@ -46,6 +47,7 @@ const ThemeSettings: React.FC<ThemeSettingsProps> = ({sections, updateSetting})
|
|||
const activeThemeName = activeTheme?.package.name?.toLowerCase() || '';
|
||||
const activeThemeAuthor = activeTheme?.package.author?.name || '';
|
||||
const hasCustomFonts = useFeatureFlag('customFonts');
|
||||
const {supportsCustomFonts} = useCustomFonts();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -70,7 +72,7 @@ const ThemeSettings: React.FC<ThemeSettingsProps> = ({sections, updateSetting})
|
|||
// should be removed once we remove the settings from the themes in 6.0
|
||||
if (hasCustomFonts) {
|
||||
const hidingSettings = themeSettingsMap[activeThemeName];
|
||||
if (hidingSettings && hidingSettings.includes(setting.key) && activeThemeAuthor === 'Ghost Foundation') {
|
||||
if (hidingSettings && hidingSettings.includes(setting.key) && activeThemeAuthor === 'Ghost Foundation' && supportsCustomFonts) {
|
||||
spaceClass += ' hidden';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import InvalidThemeModal, {FatalErrors} from './InvalidThemeModal';
|
||||
import NiceModal from '@ebay/nice-modal-react';
|
||||
import React from 'react';
|
||||
import useCustomFonts from '../../../../hooks/useCustomFonts';
|
||||
import {Button, ButtonProps, ConfirmationModal, List, ListItem, Menu, ModalPage, showToast} from '@tryghost/admin-x-design-system';
|
||||
import {JSONError} from '@tryghost/admin-x-framework/errors';
|
||||
import {Theme, isActiveTheme, isDefaultTheme, isDeletableTheme, isLegacyTheme, useActivateTheme, useDeleteTheme} from '@tryghost/admin-x-framework/api/themes';
|
||||
|
@ -48,11 +49,13 @@ const ThemeActions: React.FC<ThemeActionProps> = ({
|
|||
}) => {
|
||||
const {mutateAsync: activateTheme} = useActivateTheme();
|
||||
const {mutateAsync: deleteTheme} = useDeleteTheme();
|
||||
const {refreshActiveThemeData} = useCustomFonts();
|
||||
const handleError = useHandleError();
|
||||
|
||||
const handleActivate = async () => {
|
||||
try {
|
||||
await activateTheme(theme.name);
|
||||
refreshActiveThemeData();
|
||||
showToast({
|
||||
title: 'Theme activated',
|
||||
type: 'success',
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import NiceModal from '@ebay/nice-modal-react';
|
||||
import React, {ReactNode, useState} from 'react';
|
||||
import useCustomFonts from '../../../../hooks/useCustomFonts';
|
||||
import {Button, ConfirmationModalContent, Heading, List, ListItem, showToast} from '@tryghost/admin-x-design-system';
|
||||
import {InstalledTheme, ThemeProblem, useActivateTheme} from '@tryghost/admin-x-framework/api/themes';
|
||||
import {useHandleError} from '@tryghost/admin-x-framework/hooks';
|
||||
|
@ -42,6 +43,7 @@ const ThemeInstalledModal: React.FC<{
|
|||
onActivate?: () => void;
|
||||
}> = ({title, prompt, installedTheme, onActivate}) => {
|
||||
const {mutateAsync: activateTheme} = useActivateTheme();
|
||||
const {refreshActiveThemeData} = useCustomFonts();
|
||||
const handleError = useHandleError();
|
||||
|
||||
let errorPrompt = null;
|
||||
|
@ -85,6 +87,7 @@ const ThemeInstalledModal: React.FC<{
|
|||
try {
|
||||
const resData = await activateTheme(installedTheme.name);
|
||||
const updatedTheme = resData.themes[0];
|
||||
refreshActiveThemeData();
|
||||
|
||||
showToast({
|
||||
title: 'Theme activated',
|
||||
|
|
15
apps/admin-x-settings/src/hooks/useCustomFonts.tsx
Normal file
15
apps/admin-x-settings/src/hooks/useCustomFonts.tsx
Normal file
|
@ -0,0 +1,15 @@
|
|||
import {useActiveTheme} from '@tryghost/admin-x-framework/api/themes';
|
||||
import {useCallback} from 'react';
|
||||
|
||||
const useCustomFonts = () => {
|
||||
const activeThemes = useActiveTheme();
|
||||
const activeTheme = activeThemes.data?.themes[0];
|
||||
const supportsCustomFonts = !activeTheme?.warnings?.some(warning => warning.code === 'GS051-CUSTOM-FONTS');
|
||||
|
||||
const refreshActiveThemeData = useCallback(() => {
|
||||
activeThemes.refetch();
|
||||
}, [activeThemes]);
|
||||
|
||||
return {supportsCustomFonts, refreshActiveThemeData};
|
||||
};
|
||||
export default useCustomFonts;
|
|
@ -399,4 +399,204 @@ test.describe('Design settings', async () => {
|
|||
expect(matchingHeader).toBeDefined();
|
||||
// expect(lastRequest.previewHeader).toMatch(new RegExp(`&${expectedEncoded.replace(/\+/g, '\\+')}`));
|
||||
});
|
||||
|
||||
test('Old font settings are hidden with custom fonts support', async ({page}) => {
|
||||
toggleLabsFlag('customFonts', true);
|
||||
const {lastApiRequests} = await mockApi({page, requests: {
|
||||
...globalDataRequests,
|
||||
browseThemes: {method: 'GET', path: '/themes/', response: responseFixtures.themes},
|
||||
installTheme: {method: 'POST', path: /^\/themes\/install\/\?/, response: {
|
||||
themes: [{
|
||||
name: 'headline',
|
||||
package: {},
|
||||
active: false,
|
||||
templates: []
|
||||
}]
|
||||
}},
|
||||
activateTheme: {method: 'PUT', path: '/themes/headline/activate/', response: {
|
||||
themes: [{
|
||||
name: 'headline',
|
||||
package: {
|
||||
name: 'headline',
|
||||
author: {
|
||||
name: 'Ghost Foundation'
|
||||
}
|
||||
},
|
||||
active: true,
|
||||
templates: []
|
||||
}]
|
||||
}},
|
||||
browseCustomThemeSettings: {method: 'GET', path: '/custom_theme_settings/', response: {
|
||||
custom_theme_settings: [
|
||||
{
|
||||
type: 'select',
|
||||
options: [
|
||||
'Modern sans-serif',
|
||||
'Elegant serif'
|
||||
],
|
||||
default: 'Modern sans-serif',
|
||||
value: 'Modern sans-serif',
|
||||
key: 'title_font'
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
options: [
|
||||
'Modern sans-serif',
|
||||
'Elegant serif'
|
||||
],
|
||||
default: 'Elegant serif',
|
||||
value: 'Elegant serif',
|
||||
key: 'body_font'
|
||||
}
|
||||
]
|
||||
}},
|
||||
activeTheme: {
|
||||
method: 'GET',
|
||||
path: '/themes/active/',
|
||||
response: {
|
||||
themes: [{
|
||||
name: 'casper',
|
||||
package: {},
|
||||
active: true,
|
||||
templates: []
|
||||
}]
|
||||
}
|
||||
}
|
||||
}});
|
||||
|
||||
await page.goto('/');
|
||||
|
||||
const themeSection = page.getByTestId('theme');
|
||||
|
||||
await themeSection.getByRole('button', {name: 'Change theme'}).click();
|
||||
|
||||
const modal = page.getByTestId('theme-modal');
|
||||
|
||||
await modal.getByRole('button', {name: /Headline/}).click();
|
||||
|
||||
await modal.getByRole('button', {name: 'Install Headline'}).click();
|
||||
|
||||
await expect(page.getByTestId('confirmation-modal')).toHaveText(/installed/);
|
||||
|
||||
await page.getByRole('button', {name: 'Activate'}).click();
|
||||
|
||||
await expect(page.getByTestId('toast-success')).toHaveText(/headline is now your active theme/);
|
||||
|
||||
expect(lastApiRequests.installTheme?.url).toMatch(/\?source=github&ref=TryGhost%2FHeadline/);
|
||||
|
||||
await modal.getByRole('button', {name: 'Change theme'}).click();
|
||||
|
||||
await modal.getByRole('button', {name: 'Close'}).click();
|
||||
|
||||
const designSection = page.getByTestId('design');
|
||||
|
||||
await designSection.getByRole('button', {name: 'Customize'}).click();
|
||||
|
||||
const designModal = page.getByTestId('design-modal');
|
||||
|
||||
await designModal.getByRole('tab', {name: 'Theme'}).click();
|
||||
|
||||
const titleFontCustomThemeSetting = designModal.getByLabel('Title font');
|
||||
await expect(titleFontCustomThemeSetting).not.toBeVisible();
|
||||
|
||||
const bodyFontCustomThemeSetting = designModal.getByLabel('Body font');
|
||||
await expect(bodyFontCustomThemeSetting).not.toBeVisible();
|
||||
});
|
||||
|
||||
test('Old font settings are visible with no custom fonts support', async ({page}) => {
|
||||
toggleLabsFlag('customFonts', true);
|
||||
await mockApi({page, requests: {
|
||||
...globalDataRequests,
|
||||
browseThemes: {method: 'GET', path: '/themes/', response: responseFixtures.themes},
|
||||
activateTheme: {method: 'PUT', path: '/themes/casper/activate/', response: {
|
||||
themes: [{
|
||||
name: 'casper',
|
||||
package: {},
|
||||
active: true,
|
||||
templates: []
|
||||
}]
|
||||
}},
|
||||
browseCustomThemeSettings: {method: 'GET', path: '/custom_theme_settings/', response: {
|
||||
custom_theme_settings: [
|
||||
{
|
||||
type: 'select',
|
||||
options: [
|
||||
'Modern sans-serif',
|
||||
'Elegant serif'
|
||||
],
|
||||
default: 'Modern sans-serif',
|
||||
value: 'Modern sans-serif',
|
||||
key: 'title_font'
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
options: [
|
||||
'Modern sans-serif',
|
||||
'Elegant serif'
|
||||
],
|
||||
default: 'Elegant serif',
|
||||
value: 'Elegant serif',
|
||||
key: 'body_font'
|
||||
}
|
||||
]
|
||||
}},
|
||||
activeTheme: {
|
||||
method: 'GET',
|
||||
path: '/themes/active/',
|
||||
response: {
|
||||
themes: [{
|
||||
name: 'casper',
|
||||
package: {},
|
||||
active: true,
|
||||
templates: [],
|
||||
warnings: [{
|
||||
fatal: false,
|
||||
level: 'warning',
|
||||
rule: 'Missing support for custom fonts',
|
||||
details: 'CSS variables for Ghost font settings are not present: <code>--gh-font-heading</code>, <code>--gh-font-body</code>',
|
||||
regex: {},
|
||||
failures: [
|
||||
{
|
||||
ref: 'styles'
|
||||
}
|
||||
],
|
||||
code: 'GS051-CUSTOM-FONTS'
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}});
|
||||
|
||||
await page.goto('/');
|
||||
|
||||
const themeSection = page.getByTestId('theme');
|
||||
|
||||
await themeSection.getByRole('button', {name: 'Change theme'}).click();
|
||||
|
||||
const modal = page.getByTestId('theme-modal');
|
||||
|
||||
await modal.getByRole('button', {name: /Casper/}).click();
|
||||
|
||||
await expect(modal.getByRole('button', {name: 'Activate Casper'})).toBeVisible();
|
||||
|
||||
await expect(page.locator('iframe[title="Theme preview"]')).toHaveAttribute('src', 'https://demo.ghost.io/');
|
||||
|
||||
await modal.getByRole('button', {name: 'Change theme'}).click();
|
||||
|
||||
await modal.getByRole('button', {name: 'Close'}).click();
|
||||
|
||||
const designSection = page.getByTestId('design');
|
||||
|
||||
await designSection.getByRole('button', {name: 'Customize'}).click();
|
||||
|
||||
const designModal = page.getByTestId('design-modal');
|
||||
|
||||
await designModal.getByRole('tab', {name: 'Theme'}).click();
|
||||
|
||||
const titleFontCustomThemeSetting = designModal.getByLabel('Title font');
|
||||
await expect(titleFontCustomThemeSetting).toBeVisible();
|
||||
|
||||
const bodyFontCustomThemeSetting = designModal.getByLabel('Body font');
|
||||
await expect(bodyFontCustomThemeSetting).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -22,7 +22,19 @@ test.describe('Theme settings', async () => {
|
|||
active: true,
|
||||
templates: []
|
||||
}]
|
||||
}}
|
||||
}},
|
||||
activeTheme: {
|
||||
method: 'GET',
|
||||
path: '/themes/active/',
|
||||
response: {
|
||||
themes: [{
|
||||
name: 'casper',
|
||||
package: {},
|
||||
active: true,
|
||||
templates: []
|
||||
}]
|
||||
}
|
||||
}
|
||||
}});
|
||||
|
||||
await page.goto('/');
|
||||
|
|
Loading…
Add table
Reference in a new issue