0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-27 22:49:56 -05:00

Refactored theme demo selector functionality (#18541)

refs https://github.com/TryGhost/Product/issues/3999

Refactored the theme demo functionality to remove the hard-coded
reference to the source theme and enable the functionality for any
theme.
This commit is contained in:
Michael Barrett 2023-10-10 09:19:08 +01:00 committed by GitHub
parent 81d2fa09da
commit 9a18d43ea6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 22 deletions

View file

@ -4,8 +4,9 @@ import {DefaultHeaderTypes} from '../../utils/unsplash/UnsplashTypes';
import {ZapierTemplate} from '../settings/advanced/integrations/ZapierModal';
export type ThemeVariant = {
image: string;
category: string;
previewUrl: string;
image: string;
};
export type OfficialTheme = {

View file

@ -12,8 +12,9 @@ const hasVariants = (theme: OfficialTheme) => theme.variants && theme.variants.l
const getAllVariants = (theme: OfficialTheme) : ThemeVariant[] => {
const variants = [{
image: theme.image,
category: theme.category
category: theme.category,
previewUrl: theme.previewUrl,
image: theme.image
}];
if (theme.variants && theme.variants.length > 0) {

View file

@ -8,14 +8,26 @@ import NiceModal from '@ebay/nice-modal-react';
import PageHeader from '../../../../admin-x-ds/global/layout/PageHeader';
import React, {useState} from 'react';
import Select, {SelectOption} from '../../../../admin-x-ds/global/form/Select';
import {OfficialTheme} from '../../../providers/ServiceProvider';
import {OfficialTheme, ThemeVariant} from '../../../providers/ServiceProvider';
import {Theme} from '../../../../api/themes';
const sourceDemos = [
{label: 'News', value: 'news', url: 'https://source.ghost.io'},
{label: 'Magazine', value: 'magazine', url: 'https://source-magazine.ghost.io'},
{label: 'Newsletter', value: 'newsletter', url: 'https://source-newsletter.ghost.io'}
];
const hasVariants = (theme: OfficialTheme) => theme.variants && theme.variants.length > 0;
const getAllVariants = (theme: OfficialTheme) : ThemeVariant[] => {
const variants = [{
image: theme.image,
category: theme.category,
previewUrl: theme.previewUrl
}];
if (theme.variants && theme.variants.length > 0) {
variants.push(...theme.variants);
}
return variants;
};
const generateVariantOptionValue = (variant: ThemeVariant) => variant.category.toLowerCase();
const ThemePreview: React.FC<{
selectedTheme?: OfficialTheme;
@ -33,12 +45,29 @@ const ThemePreview: React.FC<{
onInstall
}) => {
const [previewMode, setPreviewMode] = useState('desktop');
const [currentSourceDemo, setCurrentSourceDemo] = useState<SelectOption>(sourceDemos[0]);
const [selectedVariant, setSelectedVariant] = useState<SelectOption | undefined>(undefined);
if (!selectedTheme) {
return null;
}
let previewUrl = selectedTheme.previewUrl;
const variantOptions = getAllVariants(selectedTheme).map((variant) => {
return {
label: variant.category,
value: generateVariantOptionValue(variant)
};
});
if (hasVariants(selectedTheme)) {
if (selectedVariant === undefined) {
setSelectedVariant(variantOptions[0]);
}
previewUrl = getAllVariants(selectedTheme).find(variant => generateVariantOptionValue(variant) === selectedVariant?.value)?.previewUrl || previewUrl;
}
let installButtonLabel = `Install ${selectedTheme.name}`;
if (isInstalling) {
@ -87,7 +116,7 @@ const ThemePreview: React.FC<{
backIcon
onBack={onBack}
/>
{selectedTheme.name === 'Source' ?
{hasVariants(selectedTheme) ?
<>
<span className='hidden md:!visible md:!block'></span>
<Select
@ -95,12 +124,10 @@ const ThemePreview: React.FC<{
containerClassName='text-sm font-bold'
controlClasses={{menu: 'w-24'}}
fullWidth={false}
options={sourceDemos}
selectedOption={currentSourceDemo}
options={variantOptions}
selectedOption={selectedVariant}
onSelect={(option) => {
if (option) {
setCurrentSourceDemo(option);
}
setSelectedVariant(option || undefined);
}}
/>
</> : null
@ -147,7 +174,7 @@ const ThemePreview: React.FC<{
<DesktopChrome>
<iframe
className='h-full w-full'
src={selectedTheme.name !== 'Source' ? selectedTheme?.previewUrl : sourceDemos.find(demo => demo.label === currentSourceDemo.label)?.url}
src={previewUrl}
title='Theme preview'
/>
</DesktopChrome>
@ -155,7 +182,7 @@ const ThemePreview: React.FC<{
<MobileChrome>
<iframe
className='h-full w-full'
src={selectedTheme.name !== 'Source' ? selectedTheme?.previewUrl : sourceDemos.find(demo => demo.label === currentSourceDemo.label)?.url}
src={previewUrl}
title='Theme preview'
/>
</MobileChrome>

View file

@ -19,8 +19,16 @@ ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
ref: 'default',
image: 'assets/img/themes/Source.png',
variants: [
{image: 'assets/img/themes/Source-Magazine.png', category: 'Magazine'},
{image: 'assets/img/themes/Source-Newsletter.png', category: 'Newsletter'}
{
category: 'Magazine',
previewUrl: 'https://source-magazine.ghost.io/',
image: 'assets/img/themes/Source-Magazine.png'
},
{
category: 'Newsletter',
previewUrl: 'https://source-newsletter.ghost.io/',
image: 'assets/img/themes/Source-Newsletter.png'
}
]
}, {
name: 'Casper',

View file

@ -18,8 +18,16 @@ const officialThemes = [{
ref: 'default',
image: 'assets/img/themes/Source.png',
variants: [
{image: 'assets/img/themes/Source-Magazine.png', category: 'Magazine'},
{image: 'assets/img/themes/Source-Newsletter.png', category: 'Newsletter'}
{
category: 'Magazine',
previewUrl: 'https://source-magazine.ghost.io/',
image: 'assets/img/themes/Source-Magazine.png'
},
{
category: 'Newsletter',
previewUrl: 'https://source-newsletter.ghost.io/',
image: 'assets/img/themes/Source-Newsletter.png'
}
]
}, {
name: 'Casper',