diff --git a/includes/RestApi/Themes/ThemeInstallerController.php b/includes/RestApi/Themes/ThemeInstallerController.php index 89734e3cb..d7842dbe1 100644 --- a/includes/RestApi/Themes/ThemeInstallerController.php +++ b/includes/RestApi/Themes/ThemeInstallerController.php @@ -2,11 +2,12 @@ namespace NewfoldLabs\WP\Module\Onboarding\RestApi\Themes; use NewfoldLabs\WP\Module\Onboarding\Permissions; -use NewfoldLabs\WP\Module\Onboarding\Data\Options; use NewfoldLabs\WP\Module\Onboarding\Services\ThemeInstaller; use NewfoldLabs\WP\Module\Onboarding\TaskManagers\ThemeInstallTaskManager; use NewfoldLabs\WP\Module\Onboarding\Tasks\ThemeInstallTask; - +/** + * Controller defining API's for theme install related functionalities. + */ class ThemeInstallerController extends \WP_REST_Controller { /** * The namespace of this controller's route. @@ -31,8 +32,8 @@ public function register_routes() { $this->rest_base . '/initialize', array( array( - 'methods' => \WP_REST_Server::CREATABLE, - 'callback' => array( $this, 'initialize' ), + 'methods' => \WP_REST_Server::CREATABLE, + 'callback' => array( $this, 'initialize' ), 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ), ), ) @@ -56,9 +57,9 @@ public function register_routes() { $this->rest_base . '/status', array( array( - 'methods' => \WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_status' ), - 'args' => $this->get_status_args(), + 'methods' => \WP_REST_Server::READABLE, + 'callback' => array( $this, 'get_status' ), + 'args' => $this->get_status_args(), 'permission_callback' => array( Permissions::class, 'rest_is_authorized_admin' ), ), ) @@ -91,6 +92,11 @@ public function get_install_theme_args() { ); } + /** + * Get the theme status check arguments. + * + * @return array + */ public function get_status_args() { return array( 'theme' => array( @@ -126,7 +132,7 @@ public static function initialize() { /** * Install the requested theme via a slug (theme). * - * @param \WP_REST_Request $request + * @param \WP_REST_Request $request The request object. * * @return \WP_REST_Response|\WP_Error */ @@ -166,6 +172,13 @@ public static function install( \WP_REST_Request $request ) { return $theme_install_task->execute(); } + /** + * Returns the status of a given theme slug. + * + * @param \WP_REST_Request $request The request object + * + * @return \WP_REST_Response + */ public function get_status( \WP_REST_Request $request ) { $theme = $request->get_param( 'theme' ); $activated = $request->get_param( 'activated' ); @@ -181,7 +194,7 @@ public function get_status( \WP_REST_Request $request ) { $position_in_queue = ThemeInstallTaskManager::status( $theme ); - if ( $position_in_queue !== false ) { + if ( false !== $position_in_queue ) { return new \WP_REST_Response( array( 'status' => 'installing', diff --git a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js index 2c8eba42b..21dbf016a 100644 --- a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js +++ b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignColors.js @@ -7,6 +7,10 @@ import { store as nfdOnboardingStore } from '../../../store'; import { getGlobalStyles, getThemeColors } from '../../../utils/api/themes'; import { useGlobalStylesOutput } from '../../../utils/global-styles/use-global-styles-output'; import { GlobalStylesProvider } from '../../LivePreview'; +import { + THEME_STATUS_ACTIVE, + THEME_STATUS_INIT, +} from '../../../../constants'; import Animate from '../../Animate'; const DesignColors = () => { @@ -20,17 +24,24 @@ const DesignColors = () => { const [ colorPalettes, setColorPalettes ] = useState(); const [ colorPickerCalledBy, setColorPickerCalledBy ] = useState( '' ); - const { storedPreviewSettings, currentData } = useSelect( ( select ) => { - return { - storedPreviewSettings: - select( nfdOnboardingStore ).getPreviewSettings(), - currentData: - select( nfdOnboardingStore ).getCurrentOnboardingData(), - }; - }, [] ); + const { storedPreviewSettings, currentData, themeStatus } = useSelect( + ( select ) => { + return { + storedPreviewSettings: + select( nfdOnboardingStore ).getPreviewSettings(), + currentData: + select( nfdOnboardingStore ).getCurrentOnboardingData(), + themeStatus: select( nfdOnboardingStore ).getThemeStatus(), + }; + }, + [] + ); - const { updatePreviewSettings, setCurrentOnboardingData } = - useDispatch( nfdOnboardingStore ); + const { + updatePreviewSettings, + setCurrentOnboardingData, + updateThemeStatus, + } = useDispatch( nfdOnboardingStore ); function stateToLocal( selectedColors ) { if ( selectedColors ) { @@ -188,6 +199,9 @@ const DesignColors = () => { const getColorStylesAndPatterns = async () => { const colorPalettes = await getThemeColors(); + if ( colorPalettes?.error ) { + return updateThemeStatus( THEME_STATUS_INIT ); + } setColorPalettes( colorPalettes?.body ); let selectedColors; let selectedColorsLocal; @@ -215,8 +229,9 @@ const DesignColors = () => { }; useEffect( () => { - if ( ! isLoaded ) getColorStylesAndPatterns(); - }, [ isLoaded ] ); + if ( ! isLoaded && THEME_STATUS_ACTIVE === themeStatus ) + getColorStylesAndPatterns(); + }, [ isLoaded, themeStatus ] ); const handleClick = ( colorStyle ) => { const customColorsTemp = customColors; diff --git a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignHeaderMenu.js b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignHeaderMenu.js index f8fc81a21..718294429 100644 --- a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignHeaderMenu.js +++ b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignHeaderMenu.js @@ -8,7 +8,7 @@ import { GlobalStylesProvider } from '../../../components/LivePreview'; import { THEME_STATUS_ACTIVE, - THEME_STATUS_NOT_ACTIVE, + THEME_STATUS_INIT, } from '../../../../constants'; const DesignHeaderMenu = () => { @@ -48,7 +48,7 @@ const DesignHeaderMenu = () => { currentStep.patternId ); if ( headerMenuPreviewResponse?.error ) { - return updateThemeStatus( THEME_STATUS_NOT_ACTIVE ); + return updateThemeStatus( THEME_STATUS_INIT ); } setHeaderMenuPreviewData( headerMenuPreviewResponse.body ); diff --git a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignThemeStylesPreview.js b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignThemeStylesPreview.js index dbcd6be13..87290e71e 100644 --- a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignThemeStylesPreview.js +++ b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignThemeStylesPreview.js @@ -7,7 +7,7 @@ import { getGlobalStyles } from '../../../utils/api/themes'; import { useGlobalStylesOutput } from '../../../utils/global-styles/use-global-styles-output'; import { THEME_STATUS_ACTIVE, - THEME_STATUS_NOT_ACTIVE, + THEME_STATUS_INIT, } from '../../../../constants'; import { LivePreviewSelectableCard, @@ -15,25 +15,28 @@ import { } from '../../LivePreview'; const DesignThemeStylesPreview = () => { - const MAX_PREVIEWS_PER_ROW = 3; - const [ isLoaded, setIsLoaded ] = useState( false ); const [ pattern, setPattern ] = useState(); const [ globalStyles, setGlobalStyles ] = useState(); const [ selectedStyle, setSelectedStyle ] = useState( '' ); - const { currentStep, currentData, storedPreviewSettings, themeStatus, themeVariations, } = - useSelect( ( select ) => { - return { - currentStep: select( nfdOnboardingStore ).getCurrentStep(), - currentData: - select( nfdOnboardingStore ).getCurrentOnboardingData(), - storedPreviewSettings: - select( nfdOnboardingStore ).getPreviewSettings(), - themeStatus: select( nfdOnboardingStore ).getThemeStatus(), - themeVariations: select(nfdOnboardingStore).getStepPreviewData(), - }; - }, [] ); + const { + currentStep, + currentData, + storedPreviewSettings, + themeStatus, + themeVariations, + } = useSelect( ( select ) => { + return { + currentStep: select( nfdOnboardingStore ).getCurrentStep(), + currentData: + select( nfdOnboardingStore ).getCurrentOnboardingData(), + storedPreviewSettings: + select( nfdOnboardingStore ).getPreviewSettings(), + themeStatus: select( nfdOnboardingStore ).getThemeStatus(), + themeVariations: select( nfdOnboardingStore ).getStepPreviewData(), + }; + }, [] ); const { updatePreviewSettings, @@ -47,11 +50,11 @@ const DesignThemeStylesPreview = () => { true ); if ( patternResponse?.error ) { - return updateThemeStatus( THEME_STATUS_NOT_ACTIVE ); + return updateThemeStatus( THEME_STATUS_INIT ); } const globalStylesResponse = await getGlobalStyles( true ); if ( globalStylesResponse?.error ) { - return updateThemeStatus( THEME_STATUS_NOT_ACTIVE ); + return updateThemeStatus( THEME_STATUS_INIT ); } setPattern( patternResponse?.body ); setGlobalStyles( globalStylesResponse?.body ); @@ -120,9 +123,12 @@ const DesignThemeStylesPreview = () => { + viewportWidth={ 900 } + /> ); diff --git a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignTypography.js b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignTypography.js index 644081e50..3ec587d9d 100644 --- a/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignTypography.js +++ b/src/OnboardingSPA/components/Drawer/DrawerPanel/DesignTypography.js @@ -6,6 +6,10 @@ import { store as nfdOnboardingStore } from '../../../store'; import { GlobalStylesProvider } from '../../../components/LivePreview'; import { getGlobalStyles, getThemeFonts } from '../../../utils/api/themes'; import { useGlobalStylesOutput } from '../../../utils/global-styles/use-global-styles-output'; +import { + THEME_STATUS_ACTIVE, + THEME_STATUS_INIT, +} from '../../../../constants'; const DesignTypography = () => { const drawerFontOptions = useRef(); @@ -15,20 +19,30 @@ const DesignTypography = () => { const [ fontPalettes, setFontPalettes ] = useState(); const [ isAccordionClosed, setIsAccordionClosed ] = useState( true ); - const { storedPreviewSettings, currentData } = useSelect( ( select ) => { - return { - storedPreviewSettings: - select( nfdOnboardingStore ).getPreviewSettings(), - currentData: - select( nfdOnboardingStore ).getCurrentOnboardingData(), - }; - }, [] ); + const { storedPreviewSettings, currentData, themeStatus } = useSelect( + ( select ) => { + return { + storedPreviewSettings: + select( nfdOnboardingStore ).getPreviewSettings(), + currentData: + select( nfdOnboardingStore ).getCurrentOnboardingData(), + themeStatus: select( nfdOnboardingStore ).getThemeStatus(), + }; + }, + [] + ); - const { updatePreviewSettings, setCurrentOnboardingData } = - useDispatch( nfdOnboardingStore ); + const { + updatePreviewSettings, + setCurrentOnboardingData, + updateThemeStatus, + } = useDispatch( nfdOnboardingStore ); const getFontStylesAndPatterns = async () => { const fontPalettes = await getThemeFonts(); + if ( fontPalettes?.error ) { + return updateThemeStatus( THEME_STATUS_INIT ); + } setFontPalettes( fontPalettes?.body ); if ( currentData?.data?.typography?.slug !== '' ) { @@ -51,8 +65,9 @@ const DesignTypography = () => { }; useEffect( () => { - if ( ! isLoaded ) getFontStylesAndPatterns(); - }, [ isLoaded ] ); + if ( ! isLoaded && THEME_STATUS_ACTIVE === themeStatus ) + getFontStylesAndPatterns(); + }, [ isLoaded, themeStatus ] ); const handleClick = async ( fontStyle, diff --git a/src/OnboardingSPA/components/Drawer/DrawerPanel/NavPrimary.js b/src/OnboardingSPA/components/Drawer/DrawerPanel/NavPrimary.js index 0494d4f69..fa5510f25 100644 --- a/src/OnboardingSPA/components/Drawer/DrawerPanel/NavPrimary.js +++ b/src/OnboardingSPA/components/Drawer/DrawerPanel/NavPrimary.js @@ -33,8 +33,8 @@ const NavPrimary = () => { ) ) || ( ) } diff --git a/src/OnboardingSPA/components/ExitToWordPress/index.js b/src/OnboardingSPA/components/ExitToWordPress/index.js index cddfd1a45..09285f463 100644 --- a/src/OnboardingSPA/components/ExitToWordPress/index.js +++ b/src/OnboardingSPA/components/ExitToWordPress/index.js @@ -1,10 +1,10 @@ import { useSelect } from '@wordpress/data'; -import { useLocation } from 'react-router-dom'; +import { useLocation } from 'react-router-dom'; import { chevronLeft } from '@wordpress/icons'; import { Fragment, useState } from '@wordpress/element'; -import { Button, ButtonGroup, Modal, Tooltip } from '@wordpress/components'; +import { Button, ButtonGroup, Modal } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; import classNames from 'classnames'; import { setFlow } from '../../utils/api/flow'; import { store as nfdOnboardingStore } from '../../store'; @@ -15,106 +15,136 @@ import { wpAdminPage, bluehostDashboardPage } from '../../../constants'; * Self-contained button and confirmation modal for exiting Onboarding page. * * @param {*} param0 - * @returns + * @return */ -const ExitToWordPress = ({ - text = __('Exit to WordPress', 'wp-module-onboarding'), - showIcon = true, +const ExitToWordPress = ( { + buttonText = __( 'Exit to WordPress', 'wp-module-onboarding' ), + showButtonIcon = true, showButton = true, - variant = 'secondary', - className = false, - origin, - ...props -}) => { - const [isOpen, setIsOpen] = useState(false); - const openModal = () => setIsOpen(true); - const closeModal = () => setIsOpen(false); + buttonVariant = 'secondary', + buttonClassName = false, + isModalOpen = false, + modalTitle = __( 'Exit without finishing?', 'wp-module-onboarding' ), + modalText = false, + modalPrimaryCloseButtonText = __( 'Continue', 'wp-module-onboarding' ), + modalOnClose = false, + modalExitButtonText = __( 'Exit', 'wp-module-onboarding' ), +} ) => { + const [ isOpen, setIsOpen ] = useState( isModalOpen ); + const openModal = () => setIsOpen( true ); + const closeModal = () => { + if ( typeof modalOnClose === 'function' ) { + modalOnClose(); + } + setIsOpen( false ); + }; const location = useLocation(); - const { currentData } = useSelect( - (select) => { + const { currentData, brandName } = useSelect( + ( select ) => { return { - currentData: select(nfdOnboardingStore).getCurrentOnboardingData(), + currentData: + select( nfdOnboardingStore ).getCurrentOnboardingData(), + brandName: select( nfdOnboardingStore ).getNewfoldBrandName(), }; }, - [location.pathname] + [ location.pathname ] ); - const label = __( - 'You can restart onboarding from your Bluehost Settings page.', - 'wp-module-onboarding' - ); + if ( ! modalText ) { + modalText = sprintf( + /* translators: %s: Brand */ + __( + 'You can restart onboarding from your %s Settings page.', + 'wp-module-onboarding' + ), + brandName + ); + } - async function syncSocialSettingsFinish(currentData) { + async function syncSocialSettingsFinish( currentData ) { const initialData = await getSettings(); - const result = await setSettings(currentData?.data?.socialData); - if (result?.error != null) { - console.error('Unable to Save Social Data!'); + const result = await setSettings( currentData?.data?.socialData ); + if ( result?.error !== null ) { return initialData?.body; } return result?.body; } - async function saveData(path, currentData) { - - if (currentData) { - currentData.hasExited = new Date().getTime(); + async function saveData( path, currentData ) { + if ( currentData ) { + currentData.hasExited = new Date().getTime(); // If Social Data is changed then sync it - if (path?.includes('basic-info')) { - const socialData = await syncSocialSettingsFinish(currentData); + if ( path?.includes( 'basic-info' ) ) { + const socialData = await syncSocialSettingsFinish( + currentData + ); // If Social Data is changed then Sync that also to the store - if (socialData && currentData?.data) + if ( socialData && currentData?.data ) currentData.data.socialData = socialData; } - setFlow(currentData); + setFlow( currentData ); } - //Redirect to Admin Page for normal customers + //Redirect to Admin Page for normal customers // and Bluehost Dashboard for ecommerce customers - const exitLink = exitToWordpressForEcommerce() ? bluehostDashboardPage : wpAdminPage; - window.location.replace(exitLink); + const exitLink = exitToWordpressForEcommerce() + ? bluehostDashboardPage + : wpAdminPage; + window.location.replace( exitLink ); } return ( - - {isOpen && ( + { showButton && ( + + ) } + { isOpen && ( closeModal() } > -

{label}

+

{ modalText }

-
- )} + ) }
); }; /* - * check if this is the last step + * check if this is the last step */ const exitToWordpressForEcommerce = () => { - if (window.nfdOnboarding.currentFlow == 'ecommerce') { + if ( window.nfdOnboarding.currentFlow === 'ecommerce' ) { return true; } return false; -} +}; export default ExitToWordPress; diff --git a/src/OnboardingSPA/components/LivePreview/GlobalStylesProvider/index.js b/src/OnboardingSPA/components/LivePreview/GlobalStylesProvider/index.js index 436da015f..1bde8d637 100644 --- a/src/OnboardingSPA/components/LivePreview/GlobalStylesProvider/index.js +++ b/src/OnboardingSPA/components/LivePreview/GlobalStylesProvider/index.js @@ -4,6 +4,10 @@ import { useState, useEffect } from '@wordpress/element'; import { store as nfdOnboardingStore } from '../../../store'; import { getGlobalStyles, setGlobalStyles } from '../../../utils/api/themes'; import { useGlobalStylesOutput } from '../../../utils/global-styles/use-global-styles-output'; +import { + THEME_STATUS_ACTIVE, + THEME_STATUS_INIT, +} from '../../../../constants'; /** * Global Style Parent Component @@ -16,14 +20,18 @@ import { useGlobalStylesOutput } from '../../../utils/global-styles/use-global-s const GlobalStylesProvider = ( { children } ) => { const [ isLoaded, setIsLoaded ] = useState( false ); - const { currentData, storedPreviewSettings } = useSelect( ( select ) => { - return { - currentData: - select( nfdOnboardingStore ).getCurrentOnboardingData(), - storedPreviewSettings: - select( nfdOnboardingStore ).getPreviewSettings(), - }; - }, [] ); + const { currentData, storedPreviewSettings, themeStatus } = useSelect( + ( select ) => { + return { + currentData: + select( nfdOnboardingStore ).getCurrentOnboardingData(), + storedPreviewSettings: + select( nfdOnboardingStore ).getPreviewSettings(), + themeStatus: select( nfdOnboardingStore ).getThemeStatus(), + }; + }, + [] + ); const { updateThemeStatus, updatePreviewSettings } = useDispatch( nfdOnboardingStore ); @@ -31,7 +39,7 @@ const GlobalStylesProvider = ( { children } ) => { const getStylesAndPatterns = async () => { const globalStyles = await getGlobalStyles(); if ( globalStyles?.error ) { - return updateThemeStatus( THEME_STATUS_NOT_ACTIVE ); + return updateThemeStatus( THEME_STATUS_INIT ); } let selectedGlobalStyle; if ( storedPreviewSettings?.title && storedPreviewSettings?.settings ) @@ -59,8 +67,9 @@ const GlobalStylesProvider = ( { children } ) => { }; useEffect( () => { - if ( ! isLoaded ) getStylesAndPatterns(); - }, [ isLoaded ] ); + if ( ! isLoaded && THEME_STATUS_ACTIVE === themeStatus ) + getStylesAndPatterns(); + }, [ isLoaded, themeStatus ] ); return children; }; diff --git a/src/OnboardingSPA/components/StateHandlers/Design/index.js b/src/OnboardingSPA/components/StateHandlers/Design/index.js index 74ed62aec..95aafea9c 100644 --- a/src/OnboardingSPA/components/StateHandlers/Design/index.js +++ b/src/OnboardingSPA/components/StateHandlers/Design/index.js @@ -1,10 +1,14 @@ import { useSelect, useDispatch } from '@wordpress/data'; import { Fragment, useEffect } from '@wordpress/element'; import { useViewportMatch } from '@wordpress/compose'; +import { __ } from '@wordpress/i18n'; import { StepLoader } from '../../Loaders'; import { store as nfdOnboardingStore } from '../../../store'; -import { getThemeStatus } from '../../../utils/api/themes'; +import { + getThemeStatus, + install as installTheme, +} from '../../../utils/api/themes'; import { THEME_STATUS_INIT, THEME_STATUS_INSTALLING, @@ -12,9 +16,11 @@ import { THEME_STATUS_ACTIVE, DESIGN_STEPS_THEME, THEME_INSTALL_WAIT_TIMEOUT, + THEME_STATUS_FAILURE, } from '../../../../constants'; import { StepErrorState } from '../../ErrorState'; import getContents from './contents'; +import ExitToWordPress from '../../ExitToWordPress'; const DesignStateHandler = ( { children, @@ -77,10 +83,9 @@ const DesignStateHandler = ( { enableNavigation(); }; - const handleNavigationState = ( themeStatus ) => { - switch ( themeStatus ) { - case THEME_STATUS_NOT_ACTIVE: - return handleNavigationStateCallback(); + const handleNavigationState = () => { + switch ( storedThemeStatus ) { + case THEME_STATUS_FAILURE: case THEME_STATUS_ACTIVE: return handleNavigationStateCallback(); default: @@ -89,7 +94,7 @@ const DesignStateHandler = ( { }; useEffect( async () => { - handleNavigationState( storedThemeStatus ); + handleNavigationState(); if ( storedThemeStatus === THEME_STATUS_INIT ) { const themeStatus = await checkThemeStatus(); @@ -106,9 +111,43 @@ const DesignStateHandler = ( { } }, [ storedThemeStatus ] ); + const installThemeManually = async () => { + updateThemeStatus( THEME_STATUS_INSTALLING ); + const themeInstallStatus = await installTheme( + DESIGN_STEPS_THEME, + true, + false + ); + if ( themeInstallStatus.error ) { + return updateThemeStatus( THEME_STATUS_FAILURE ); + } + + return window.location.reload(); + }; + const handleRender = () => { switch ( storedThemeStatus ) { case THEME_STATUS_NOT_ACTIVE: + return ( + + ); + case THEME_STATUS_FAILURE: return ( { - const { setIsDrawerSuppressed, setIsHeaderNavigationEnabled, setSidebarActiveView } = - useDispatch( nfdOnboardingStore ); + const { + setIsDrawerSuppressed, + setIsHeaderNavigationEnabled, + setSidebarActiveView, + updateThemeStatus, + } = useDispatch( nfdOnboardingStore ); const navigate = useNavigate(); const [ isError, setIsError ] = useState( false ); @@ -34,18 +39,21 @@ const StepComplete = () => { const contents = getContents( brandName ); const checkFlowComplete = async () => { - await Promise.all( [ completeFlowRequest(), setSiteFeaturesRequest() ] ).then( - ( values ) => - values.forEach( ( value ) => { - // If any Request returns False then Show Error - if ( ! value ) { - setIsHeaderNavigationEnabled( true ); - return setIsError( true ); - } - } ) + await Promise.all( [ + completeFlowRequest(), + setSiteFeaturesRequest(), + ] ).then( ( values ) => + values.forEach( ( value ) => { + // If any Request returns False then Show Error + if ( ! value ) { + setIsHeaderNavigationEnabled( true ); + return setIsError( true ); + } + } ) ); navigate( nextStep.path ); + updateThemeStatus( THEME_STATUS_INIT ); }; async function completeFlowRequest() { @@ -69,13 +77,13 @@ const StepComplete = () => { setIsHeaderNavigationEnabled( false ); setIsDrawerSuppressed( true ); setSidebarActiveView( false ); - } + }; useEffect( () => { checkFlowComplete(); }, [] ); return ( - + { isError ? ( { const [ isLoaded, setIsLoaded ] = useState( false ); const [ pattern, setPattern ] = useState(); - const { currentStep } = useSelect( ( select ) => { + const { currentStep, themeStatus } = useSelect( ( select ) => { return { currentStep: select( nfdOnboardingStore ).getStepFromPath( location.pathname ), + themeStatus: select( nfdOnboardingStore ).getThemeStatus(), }; }, [] ); @@ -40,15 +42,16 @@ const StepDesignColors = () => { const getStylesAndPatterns = async () => { const pattern = await getPatterns( currentStep.patternId, true ); if ( pattern?.error ) { - return updateThemeStatus( THEME_STATUS_NOT_ACTIVE ); + return updateThemeStatus( THEME_STATUS_INIT ); } setPattern( pattern?.body ); setIsLoaded( true ); }; useEffect( () => { - if ( ! isLoaded ) getStylesAndPatterns(); - }, [ isLoaded ] ); + if ( ! isLoaded && THEME_STATUS_ACTIVE === themeStatus ) + getStylesAndPatterns(); + }, [ isLoaded, themeStatus ] ); return ( diff --git a/src/OnboardingSPA/pages/Steps/DesignHomepageMenu/index.js b/src/OnboardingSPA/pages/Steps/DesignHomepageMenu/index.js index ccc983dc8..1d8a9d1f1 100644 --- a/src/OnboardingSPA/pages/Steps/DesignHomepageMenu/index.js +++ b/src/OnboardingSPA/pages/Steps/DesignHomepageMenu/index.js @@ -8,7 +8,7 @@ import CommonLayout from '../../../components/Layouts/Common'; import { VIEW_NAV_DESIGN, THEME_STATUS_ACTIVE, - THEME_STATUS_NOT_ACTIVE, + THEME_STATUS_INIT, SIDEBAR_LEARN_MORE, } from '../../../../constants'; import HeadingWithSubHeading from '../../../components/HeadingWithSubHeading'; @@ -103,7 +103,7 @@ const StepDesignHomepageMenu = () => { async function getHomepagePatternsData() { const homepagePatternData = await getPatterns( currentStep.patternId ); if ( homepagePatternData?.error ) { - return updateThemeStatus( THEME_STATUS_NOT_ACTIVE ); + return updateThemeStatus( THEME_STATUS_INIT ); } setHomepagePattern( refactorPatterns( homepagePatternData ) ); diff --git a/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Menu/index.js b/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Menu/index.js index a2c56b1aa..c7a09775b 100644 --- a/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Menu/index.js +++ b/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Menu/index.js @@ -11,7 +11,7 @@ import { getGlobalStyles } from '../../../../utils/api/themes'; import { VIEW_NAV_DESIGN, THEME_STATUS_ACTIVE, - THEME_STATUS_NOT_ACTIVE, + THEME_STATUS_INIT, SIDEBAR_LEARN_MORE, } from '../../../../../constants'; import { DesignStateHandler } from '../../../../components/StateHandlers'; @@ -69,11 +69,11 @@ const StepDesignThemeStylesMenu = () => { true ); if ( patternsResponse?.error ) { - return updateThemeStatus( THEME_STATUS_NOT_ACTIVE ); + return updateThemeStatus( THEME_STATUS_INIT ); } const globalStylesResponse = await getGlobalStyles( true ); if ( globalStylesResponse?.error ) { - return updateThemeStatus( THEME_STATUS_NOT_ACTIVE ); + return updateThemeStatus( THEME_STATUS_INIT ); } setPattern( patternsResponse?.body ); setGlobalStyles( globalStylesResponse?.body ); diff --git a/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Preview/index.js b/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Preview/index.js index fba1ff6e7..82e25251c 100644 --- a/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Preview/index.js +++ b/src/OnboardingSPA/pages/Steps/DesignThemeStyles/Preview/index.js @@ -13,7 +13,7 @@ import CommonLayout from '../../../../components/Layouts/Common'; import { VIEW_DESIGN_THEME_STYLES_PREVIEW, THEME_STATUS_ACTIVE, - THEME_STATUS_NOT_ACTIVE, + THEME_STATUS_INIT, SIDEBAR_LEARN_MORE, } from '../../../../../constants'; import { store as nfdOnboardingStore } from '../../../../store'; @@ -70,7 +70,7 @@ const StepDesignThemeStylesPreview = () => { true ); if ( patternsResponse?.error ) { - return updateThemeStatus( THEME_STATUS_NOT_ACTIVE ); + return updateThemeStatus( THEME_STATUS_INIT ); } setPattern( patternsResponse?.body ); setIsLoaded( true ); diff --git a/src/OnboardingSPA/pages/Steps/DesignTypography/index.js b/src/OnboardingSPA/pages/Steps/DesignTypography/index.js index 3eb6e727e..8b9f43768 100644 --- a/src/OnboardingSPA/pages/Steps/DesignTypography/index.js +++ b/src/OnboardingSPA/pages/Steps/DesignTypography/index.js @@ -7,8 +7,9 @@ import { store as nfdOnboardingStore } from '../../../store'; import CommonLayout from '../../../components/Layouts/Common'; import { SIDEBAR_LEARN_MORE, - THEME_STATUS_NOT_ACTIVE, + THEME_STATUS_INIT, VIEW_DESIGN_TYPOGRAPHY, + THEME_STATUS_ACTIVE, } from '../../../../constants'; import { DesignStateHandler } from '../../../components/StateHandlers'; import { @@ -21,11 +22,12 @@ const StepDesignTypography = () => { const [ pattern, setPattern ] = useState(); const [ isLoaded, setIsLoaded ] = useState( false ); - const { currentStep } = useSelect( ( select ) => { + const { currentStep, themeStatus } = useSelect( ( select ) => { return { currentStep: select( nfdOnboardingStore ).getStepFromPath( location.pathname ), + themeStatus: select( nfdOnboardingStore ).getThemeStatus(), }; }, [] ); @@ -43,15 +45,16 @@ const StepDesignTypography = () => { true ); if ( patternsResponse?.error ) { - return updateThemeStatus( THEME_STATUS_NOT_ACTIVE ); + return updateThemeStatus( THEME_STATUS_INIT ); } setPattern( patternsResponse?.body ); setIsLoaded( true ); }; useEffect( () => { - if ( ! isLoaded ) getFontPatterns(); - }, [ isLoaded ] ); + if ( ! isLoaded && THEME_STATUS_ACTIVE === themeStatus ) + getFontPatterns(); + }, [ isLoaded, themeStatus ] ); return ( diff --git a/src/OnboardingSPA/pages/Steps/SitePages/index.js b/src/OnboardingSPA/pages/Steps/SitePages/index.js index 6f05f3ef1..cc7a4e907 100644 --- a/src/OnboardingSPA/pages/Steps/SitePages/index.js +++ b/src/OnboardingSPA/pages/Steps/SitePages/index.js @@ -8,7 +8,7 @@ import HeadingWithSubHeading from '../../../components/HeadingWithSubHeading'; import { getPatterns } from '../../../utils/api/patterns'; import { THEME_STATUS_ACTIVE, - THEME_STATUS_NOT_ACTIVE, + THEME_STATUS_INIT, SIDEBAR_LEARN_MORE, VIEW_NAV_DESIGN, } from '../../../../constants'; @@ -54,7 +54,7 @@ const StepSitePages = () => { const getSitePages = async () => { const sitePagesResponse = await getPatterns( currentStep.patternId ); if ( sitePagesResponse?.error ) { - return updateThemeStatus( THEME_STATUS_NOT_ACTIVE ); + return updateThemeStatus( THEME_STATUS_INIT ); } if ( sitePagesResponse?.body ) { setSitePages( sitePagesResponse.body ); diff --git a/src/OnboardingSPA/utils/api/themes.js b/src/OnboardingSPA/utils/api/themes.js index ae4b9f238..273bba53b 100644 --- a/src/OnboardingSPA/utils/api/themes.js +++ b/src/OnboardingSPA/utils/api/themes.js @@ -18,6 +18,24 @@ const init = () => { } ); }; +const install = async ( theme, activate = true, queue = true ) => { + if ( typeof theme !== 'string' ) { + return false; + } + + return await resolve( + apiFetch( { + url: onboardingRestURL( 'themes/install' ), + method: 'POST', + data: { + theme, + activate, + queue, + }, + } ) + ); +}; + const getGlobalStyles = async ( variations = false ) => { return await resolve( apiFetch( { @@ -71,4 +89,5 @@ export { getThemeStatus, getThemeColors, getThemeFonts, + install, }; diff --git a/src/constants.js b/src/constants.js index 26b024944..36d2121d0 100644 --- a/src/constants.js +++ b/src/constants.js @@ -33,11 +33,12 @@ export const NFD_PLUGINS_QUERY_PARAM = 'nfd_plugins'; export const NFD_THEMES_QUERY_PARAM = 'nfd_themes'; // [TODO] Read the theme from flow data once we have the themes step. -export const DESIGN_STEPS_THEME = 'nfd_slug_yith_wonder' +export const DESIGN_STEPS_THEME = 'nfd_slug_yith_wonder'; export const THEME_STATUS_INIT = 'init'; export const THEME_STATUS_NOT_ACTIVE = 'inactive'; export const THEME_STATUS_INSTALLING = 'installing'; export const THEME_STATUS_ACTIVE = 'activated'; +export const THEME_STATUS_FAILURE = 'failed'; export const THEME_INSTALL_WAIT_TIMEOUT = 30000 export const ECOMMERCE_STEPS_PLUGIN = 'woocommerce'