/** * External dependencies */ import { __ } from '@wordpress/i18n'; import apiFetch from '@wordpress/api-fetch'; import { Button } from '@wordpress/components'; import { Component, Fragment } from '@wordpress/element'; import { compose } from '@wordpress/compose'; import { difference, filter } from 'lodash'; import { withDispatch } from '@wordpress/data'; /** * WooCommerce dependencies */ import { Card, Stepper, TextControl, ImageUpload, } from '@woocommerce/components'; import { getHistory, getNewPath } from '@woocommerce/navigation'; import { getSetting, setSetting } from '@woocommerce/wc-admin-settings'; /** * Internal dependencies */ import { queueRecordEvent, recordEvent } from 'lib/tracks'; import { WC_ADMIN_NAMESPACE } from 'wc-api/constants'; import withSelect from 'wc-api/with-select'; class Appearance extends Component { constructor( props ) { super( props ); const { hasHomepage, hasProducts } = getSetting( 'onboarding', {} ); this.stepVisibility = { homepage: ! hasHomepage, import: ! hasProducts, }; this.state = { isDirty: false, isPending: false, logo: null, stepIndex: 0, storeNoticeText: props.options.woocommerce_demo_store_notice || '', }; this.completeStep = this.completeStep.bind( this ); this.createHomepage = this.createHomepage.bind( this ); this.importProducts = this.importProducts.bind( this ); this.updateLogo = this.updateLogo.bind( this ); this.updateNotice = this.updateNotice.bind( this ); } componentDidMount() { const { themeMods } = getSetting( 'onboarding', {} ); if ( themeMods.custom_logo ) { /* eslint-disable react/no-did-mount-set-state */ this.setState( { logo: { id: themeMods.custom_logo } } ); /* eslint-enable react/no-did-mount-set-state */ } } async componentDidUpdate( prevProps ) { const { isPending, logo, stepIndex } = this.state; const { createNotice, errors, hasErrors, isRequesting, options, } = this.props; const step = this.getSteps()[ stepIndex ].key; const isRequestSuccessful = ! isRequesting && prevProps.isRequesting && ! hasErrors; if ( logo && ! logo.url && ! isPending ) { /* eslint-disable react/no-did-update-set-state */ this.setState( { isPending: true } ); wp.media .attachment( logo.id ) .fetch() .then( () => { const logoUrl = wp.media.attachment( logo.id ).get( 'url' ); this.setState( { isPending: false, logo: { id: logo.id, url: logoUrl }, } ); } ); /* eslint-enable react/no-did-update-set-state */ } if ( options.woocommerce_demo_store_notice && prevProps.options.woocommerce_demo_store_notice !== options.woocommerce_demo_store_notice ) { /* eslint-disable react/no-did-update-set-state */ this.setState( { storeNoticeText: options.woocommerce_demo_store_notice, } ); /* eslint-enable react/no-did-update-set-state */ } if ( step === 'logo' && isRequestSuccessful ) { createNotice( 'success', __( 'Store logo updated sucessfully.', 'woocommerce-admin' ) ); this.completeStep(); } if ( step === 'notice' && isRequestSuccessful ) { createNotice( 'success', __( "🎨 Your store is looking great! Don't forget to continue personalizing it.", 'woocommerce-admin' ) ); this.completeStep(); } const newErrors = difference( errors, prevProps.errors ); newErrors.map( ( error ) => createNotice( 'error', error ) ); } completeStep() { const { stepIndex } = this.state; const nextStep = this.getSteps()[ stepIndex + 1 ]; if ( nextStep ) { this.setState( { stepIndex: stepIndex + 1 } ); } else { getHistory().push( getNewPath( {}, '/', {} ) ); } } importProducts() { const { createNotice } = this.props; this.setState( { isPending: true } ); recordEvent( 'tasklist_appearance_import_demo', {} ); apiFetch( { path: `${ WC_ADMIN_NAMESPACE }/onboarding/tasks/import_sample_products`, method: 'POST', } ) .then( ( result ) => { if ( result.failed && result.failed.length ) { createNotice( 'error', __( 'There was an error importing some of the demo products.', 'woocommerce-admin' ) ); } else { createNotice( 'success', __( 'All demo products have been imported.', 'woocommerce-admin' ) ); setSetting( 'onboarding', { ...getSetting( 'onboarding', {} ), hasProducts: true, } ); } this.setState( { isPending: false } ); this.completeStep(); } ) .catch( ( error ) => { createNotice( 'error', error.message ); this.setState( { isPending: false } ); } ); } createHomepage() { const { createNotice } = this.props; this.setState( { isPending: true } ); recordEvent( 'tasklist_appearance_create_homepage', { create_homepage: true, } ); apiFetch( { path: '/wc-admin/onboarding/tasks/create_homepage', method: 'POST', } ) .then( response => { createNotice( response.status, response.message, { actions: response.edit_post_link ? [ { label: __( 'Customize', 'woocommerce-admin' ), onClick: () => { queueRecordEvent( 'tasklist_appearance_customize_homepage', {} ); window.location = `${ response.edit_post_link }&wc_onboarding_active_task=homepage`; }, }, ] : null, } ); this.setState( { isPending: false } ); this.completeStep(); } ) .catch( ( error ) => { createNotice( 'error', error.message ); this.setState( { isPending: false } ); } ); } updateLogo() { const { updateOptions } = this.props; const { logo } = this.state; const { stylesheet, themeMods } = getSetting( 'onboarding', {} ); const updatedThemeMods = { ...themeMods, custom_logo: logo ? logo.id : null, }; recordEvent( 'tasklist_appearance_upload_logo' ); setSetting( 'onboarding', { ...getSetting( 'onboarding', {} ), themeMods: updatedThemeMods, } ); updateOptions( { [ `theme_mods_${ stylesheet }` ]: updatedThemeMods, } ); } updateNotice() { const { updateOptions } = this.props; const { storeNoticeText } = this.state; recordEvent( 'tasklist_appearance_set_store_notice', { added_text: Boolean( storeNoticeText.length ), } ); setSetting( 'onboarding', { ...getSetting( 'onboarding', {} ), isAppearanceComplete: true, } ); updateOptions( { woocommerce_task_list_appearance_complete: true, woocommerce_demo_store: storeNoticeText.length ? 'yes' : 'no', woocommerce_demo_store_notice: storeNoticeText, } ); } getSteps() { const { isDirty, isPending, logo, storeNoticeText } = this.state; const { isRequesting } = this.props; const steps = [ { key: 'import', label: __( 'Import demo products', 'woocommerce-admin' ), description: __( 'We’ll add some products that will make it easier to see what your store looks like', 'woocommerce-admin' ), content: ( ), visible: this.stepVisibility.import, }, { key: 'homepage', label: __( 'Create a custom homepage', 'woocommerce-admin' ), description: __( 'Create a new homepage and customize it to suit your needs', 'woocommerce-admin' ), content: ( ), visible: this.stepVisibility.homepage, }, { key: 'logo', label: __( 'Upload a logo', 'woocommerce-admin' ), description: __( 'Ensure your store is on-brand by adding your logo', 'woocommerce-admin' ), content: isPending ? null : ( this.setState( { isDirty: true, logo: image } ) } /> ), visible: true, }, { key: 'notice', label: __( 'Set a store notice', 'woocommerce-admin' ), description: __( 'Optionally display a prominent notice across all pages of your store', 'woocommerce-admin' ), content: ( this.setState( { storeNoticeText: value } ) } /> ), visible: true, }, ]; return filter( steps, ( step ) => step.visible ); } render() { const { isPending, stepIndex } = this.state; const { isRequesting, hasErrors } = this.props; const currentStep = this.getSteps()[ stepIndex ].key; return (
); } } export default compose( withSelect( ( select ) => { const { getOptions, getOptionsError, isUpdateOptionsRequesting, } = select( 'wc-api' ); const { stylesheet } = getSetting( 'onboarding', {} ); const options = getOptions( [ 'woocommerce_demo_store', 'woocommerce_demo_store_notice', ] ); const errors = []; const uploadLogoError = getOptionsError( [ `theme_mods_${ stylesheet }`, ] ); const storeNoticeError = getOptionsError( [ 'woocommerce_demo_store', 'woocommerce_demo_store_notice', ] ); if ( uploadLogoError ) { errors.push( uploadLogoError.message ); } if ( storeNoticeError ) { errors.push( storeNoticeError.message ); } const hasErrors = Boolean( errors.length ); const isRequesting = Boolean( isUpdateOptionsRequesting( [ `theme_mods_${ stylesheet }` ] ) ) || Boolean( isUpdateOptionsRequesting( [ 'woocommerce_task_list_appearance_complete', 'woocommerce_demo_store', 'woocommerce_demo_store_notice', ] ) ); return { errors, getOptionsError, hasErrors, isRequesting, options }; } ), withDispatch( ( dispatch ) => { const { createNotice } = dispatch( 'core/notices' ); const { updateOptions } = dispatch( 'wc-api' ); return { createNotice, updateOptions, }; } ) )( Appearance );