From 010be7fd3d29006849936d5cd130a50c59cb12c3 Mon Sep 17 00:00:00 2001 From: Peter Zimon Date: Wed, 14 Jun 2023 10:56:58 +0200 Subject: [PATCH] Updated theme preview in AdminX refs. https://github.com/TryGhost/Team/issues/3432 --- .../admin-x-ds/global/layout/PageHeader.tsx | 2 +- .../src/admin-x-ds/global/modal/Modal.tsx | 10 +- .../components/settings/site/ThemeModal.tsx | 163 ++++++++---------- .../settings/site/theme/OfficialThemes.tsx | 6 +- .../settings/site/theme/ThemePreview.tsx | 82 ++++++++- 5 files changed, 155 insertions(+), 108 deletions(-) diff --git a/ghost/admin-x-settings/src/admin-x-ds/global/layout/PageHeader.tsx b/ghost/admin-x-settings/src/admin-x-ds/global/layout/PageHeader.tsx index 1136a312b5..bfe36f5bf7 100644 --- a/ghost/admin-x-settings/src/admin-x-ds/global/layout/PageHeader.tsx +++ b/ghost/admin-x-settings/src/admin-x-ds/global/layout/PageHeader.tsx @@ -28,7 +28,7 @@ const PageHeader: React.FC = ({ children }) => { const containerClasses = clsx( - 'h-[74px] p-5 px-7', + 'z-50 h-[74px] p-5 px-7', !children && 'flex items-center justify-between gap-3', sticky && 'sticky top-0', containerClassName diff --git a/ghost/admin-x-settings/src/admin-x-ds/global/modal/Modal.tsx b/ghost/admin-x-settings/src/admin-x-ds/global/modal/Modal.tsx index 652e17071c..945bcd1b52 100644 --- a/ghost/admin-x-settings/src/admin-x-ds/global/modal/Modal.tsx +++ b/ghost/admin-x-settings/src/admin-x-ds/global/modal/Modal.tsx @@ -29,6 +29,7 @@ export interface ModalProps { backDrop?: boolean; backDropClick?: boolean; stickyFooter?: boolean; + scrolling?: boolean; } const Modal: React.FC = ({ @@ -46,7 +47,8 @@ const Modal: React.FC = ({ children, backDrop = true, backDropClick = true, - stickyFooter = false + stickyFooter = false, + scrolling = true }) => { const modal = useModal(); @@ -75,10 +77,10 @@ const Modal: React.FC = ({ } let modalClasses = clsx( - 'relative z-50 mx-auto flex max-h-[100%] w-full flex-col justify-between overflow-y-auto overflow-x-hidden rounded bg-white shadow-xl' - // !stickyFooter && ' overflow-hidden' + 'relative z-50 mx-auto flex max-h-[100%] w-full flex-col justify-between overflow-x-hidden rounded bg-white shadow-xl', + scrolling ? 'overflow-y-auto' : 'overflow-y-hidden' ); - let backdropClasses = clsx('fixed inset-0 z-40 h-[100vh] w-[100vw] overflow-y-scroll '); + let backdropClasses = clsx('fixed inset-0 z-40 h-[100vh] w-[100vw]'); let padding = ''; diff --git a/ghost/admin-x-settings/src/components/settings/site/ThemeModal.tsx b/ghost/admin-x-settings/src/components/settings/site/ThemeModal.tsx index 4a05aae614..44045344ca 100644 --- a/ghost/admin-x-settings/src/components/settings/site/ThemeModal.tsx +++ b/ghost/admin-x-settings/src/components/settings/site/ThemeModal.tsx @@ -1,15 +1,13 @@ import AdvancedThemeSettings from './theme/AdvancedThemeSettings'; -import Breadcrumbs from '../../../admin-x-ds/global/Breadcrumbs'; import Button from '../../../admin-x-ds/global/Button'; -import ButtonGroup from '../../../admin-x-ds/global/ButtonGroup'; import FileUpload from '../../../admin-x-ds/global/form/FileUpload'; import Modal from '../../../admin-x-ds/global/modal/Modal'; -import NewThemePreview from './theme/ThemePreview'; import NiceModal, {NiceModalHandler, useModal} from '@ebay/nice-modal-react'; import OfficialThemes from './theme/OfficialThemes'; import PageHeader from '../../../admin-x-ds/global/layout/PageHeader'; import React, {useState} from 'react'; import TabView from '../../../admin-x-ds/global/TabView'; +import ThemePreview from './theme/ThemePreview'; import {OfficialTheme} from '../../../models/themes'; import {Theme} from '../../../types/api'; import {showToast} from '../../../admin-x-ds/global/Toast'; @@ -23,10 +21,11 @@ interface ThemeToolbarProps { modal: NiceModalHandler>; themes: Theme[]; setThemes: (themes: Theme[]) => void; + setPreviewMode: (mode: string) => void; + previewMode: string; } interface ThemeModalContentProps { - selectedTheme: OfficialTheme|null; onSelectTheme: (theme: OfficialTheme|null) => void; currentTab: string; themes: Theme[]; @@ -34,112 +33,56 @@ interface ThemeModalContentProps { } const ThemeToolbar: React.FC = ({ - selectedTheme, setCurrentTab, - setSelectedTheme, modal, themes, setThemes }) => { const api = useApi(); + const left = + { + setCurrentTab(id); + }} />; - let left, right; + const right = +
+ { + const data = await api.themes.upload({file}); + const uploadedTheme = data.themes[0]; + setThemes([...themes, uploadedTheme]); + showToast({ + message: `Theme uploaded - ${uploadedTheme.name}` + }); + }}>Upload theme +
; - if (selectedTheme) { - const installedTheme = themes.find(theme => theme.name.toLowerCase() === selectedTheme.name.toLowerCase()); - - left = -
- { - setCurrentTab('official'); - setSelectedTheme(null); - }}, - {label: selectedTheme.name} - ]} - /> -
; - - right = -
- -
; - } else { - left = - { - setCurrentTab(id); - }} />; - - right = -
- { - const data = await api.themes.upload({file}); - const uploadedTheme = data.themes[0]; - setThemes([...themes, uploadedTheme]); - showToast({ - message: `Theme uploaded - ${uploadedTheme.name}` - }); - }}>Upload theme -
; - } - - return ; + return ; }; const ThemeModalContent: React.FC = ({ currentTab, - selectedTheme, onSelectTheme, themes, setThemes }) => { switch (currentTab) { case 'official': - if (selectedTheme) { - return ( - - ); - } else { - return ( - - ); - } + return ( + + ); case 'installed': return ( = ({ const ChangeThemeModal = NiceModal.create(() => { const [currentTab, setCurrentTab] = useState('official'); const [selectedTheme, setSelectedTheme] = useState(null); + const [previewMode, setPreviewMode] = useState('desktop'); const modal = useModal(); const {themes, setThemes} = useThemes(); + const api = useApi(); const onSelectTheme = (theme: OfficialTheme|null) => { setSelectedTheme(theme); }; + let installedTheme; + let onInstall; + if (selectedTheme) { + installedTheme = themes.find(theme => theme.name.toLowerCase() === selectedTheme!.name.toLowerCase()); + onInstall = async () => { + const data = await api.themes.install(selectedTheme.ref); + const newlyInstalledTheme = data.themes[0]; + setThemes([ + ...themes.map(theme => ({...theme, active: false})), + newlyInstalledTheme + ]); + showToast({ + message: `Theme installed - ${newlyInstalledTheme.name}` + }); + setCurrentTab('installed'); + }; + } + return (
+ {selectedTheme && + { + setSelectedTheme(null); + }} + onInstall={onInstall} /> + } +
Themes
{officialThemes.map((theme) => { @@ -139,10 +139,10 @@ const OfficialThemes: React.FC<{ onSelectTheme?.(theme); }}> {/* {theme.name} */} -
+
Headline Theme
diff --git a/ghost/admin-x-settings/src/components/settings/site/theme/ThemePreview.tsx b/ghost/admin-x-settings/src/components/settings/site/theme/ThemePreview.tsx index 035fc26336..6ec7702b12 100644 --- a/ghost/admin-x-settings/src/components/settings/site/theme/ThemePreview.tsx +++ b/ghost/admin-x-settings/src/components/settings/site/theme/ThemePreview.tsx @@ -1,20 +1,88 @@ -import React from 'react'; +import Breadcrumbs from '../../../../admin-x-ds/global/Breadcrumbs'; +import Button from '../../../../admin-x-ds/global/Button'; +import ButtonGroup from '../../../../admin-x-ds/global/ButtonGroup'; +import MobileChrome from '../../../../admin-x-ds/global/chrome/MobileChrome'; +import PageHeader from '../../../../admin-x-ds/global/layout/PageHeader'; +import React, {useState} from 'react'; import {OfficialTheme} from '../../../../models/themes'; -const NewThemePreview: React.FC<{ +const ThemePreview: React.FC<{ selectedTheme?: OfficialTheme; + onBack: () => void; + themeInstalled?: boolean; + installButtonLabel?: string; + onInstall?: () => void; }> = ({ - selectedTheme + selectedTheme, + onBack, + themeInstalled, + installButtonLabel, + onInstall }) => { + const [previewMode, setPreviewMode] = useState('desktop'); + if (!selectedTheme) { return null; } + + const left = +
+ +
; + + const right = +
+ { + setPreviewMode('desktop'); + } + }, + { + icon: 'mobile', + iconColorClass: (previewMode === 'mobile' ? 'text-black' : 'text-grey-500'), + link: true, + size: 'sm', + onClick: () => { + setPreviewMode('mobile'); + } + } + ]} + /> +
; + return ( -
-