2019-09-02 03:45:56 +00:00
|
|
|
|
/** @format */
|
|
|
|
|
/**
|
|
|
|
|
* External dependencies
|
|
|
|
|
*/
|
|
|
|
|
import { __ } from '@wordpress/i18n';
|
2019-09-06 02:06:29 +00:00
|
|
|
|
import apiFetch from '@wordpress/api-fetch';
|
2019-10-09 23:00:33 +00:00
|
|
|
|
import { Button, ImageUpload } from 'newspack-components';
|
2019-09-02 03:45:56 +00:00
|
|
|
|
import { Component, Fragment } from '@wordpress/element';
|
|
|
|
|
import { compose } from '@wordpress/compose';
|
|
|
|
|
import { difference, filter } from 'lodash';
|
|
|
|
|
import { withDispatch } from '@wordpress/data';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* WooCommerce dependencies
|
|
|
|
|
*/
|
2019-10-09 23:00:33 +00:00
|
|
|
|
import { Card, Stepper, TextControl } from '@woocommerce/components';
|
2019-09-02 03:45:56 +00:00
|
|
|
|
import { getHistory, getNewPath } from '@woocommerce/navigation';
|
2019-10-07 11:51:25 +00:00
|
|
|
|
import { getSetting, setSetting } from '@woocommerce/wc-admin-settings';
|
2019-09-02 03:45:56 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Internal dependencies
|
|
|
|
|
*/
|
2019-09-06 14:18:44 +00:00
|
|
|
|
import { WC_ADMIN_NAMESPACE } from 'wc-api/constants';
|
2019-09-02 03:45:56 +00:00
|
|
|
|
import withSelect from 'wc-api/with-select';
|
2019-10-07 20:27:34 +00:00
|
|
|
|
import { recordEvent } from 'lib/tracks';
|
2019-09-02 03:45:56 +00:00
|
|
|
|
|
|
|
|
|
class Appearance extends Component {
|
|
|
|
|
constructor( props ) {
|
|
|
|
|
super( props );
|
2019-10-07 11:51:25 +00:00
|
|
|
|
const { hasHomepage, hasProducts } = getSetting( 'onboarding', {} );
|
2019-09-02 03:45:56 +00:00
|
|
|
|
|
2019-09-06 02:06:29 +00:00
|
|
|
|
this.stepVisibility = {
|
2019-10-07 11:51:25 +00:00
|
|
|
|
homepage: ! hasHomepage,
|
|
|
|
|
import: ! hasProducts,
|
2019-09-06 02:06:29 +00:00
|
|
|
|
};
|
|
|
|
|
|
2019-09-02 03:45:56 +00:00
|
|
|
|
this.state = {
|
2019-09-06 02:06:29 +00:00
|
|
|
|
isPending: false,
|
2019-09-02 03:45:56 +00:00
|
|
|
|
logo: null,
|
|
|
|
|
stepIndex: 0,
|
|
|
|
|
storeNoticeText: props.options.woocommerce_demo_store_notice || '',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.completeStep = this.completeStep.bind( this );
|
2019-09-06 14:18:44 +00:00
|
|
|
|
this.createHomepage = this.createHomepage.bind( this );
|
2019-09-06 02:06:29 +00:00
|
|
|
|
this.importProducts = this.importProducts.bind( this );
|
2019-09-02 03:45:56 +00:00
|
|
|
|
this.updateLogo = this.updateLogo.bind( this );
|
|
|
|
|
this.updateNotice = this.updateNotice.bind( this );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async componentDidUpdate( prevProps ) {
|
|
|
|
|
const { stepIndex } = this.state;
|
|
|
|
|
const { createNotice, errors, hasErrors, isRequesting, options, themeMods } = this.props;
|
|
|
|
|
const step = this.getSteps()[ stepIndex ].key;
|
|
|
|
|
const isRequestSuccessful = ! isRequesting && prevProps.isRequesting && ! hasErrors;
|
|
|
|
|
|
|
|
|
|
if ( themeMods && prevProps.themeMods.custom_logo !== themeMods.custom_logo ) {
|
|
|
|
|
await wp.media.attachment( themeMods.custom_logo ).fetch();
|
|
|
|
|
const logoUrl = wp.media.attachment( themeMods.custom_logo ).get( 'url' );
|
|
|
|
|
/* eslint-disable react/no-did-update-set-state */
|
|
|
|
|
this.setState( { logo: { id: themeMods.custom_logo, 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 ( 'logo' === step && isRequestSuccessful ) {
|
|
|
|
|
createNotice( 'success', __( 'Store logo updated sucessfully.', 'woocommerce-admin' ) );
|
|
|
|
|
this.completeStep();
|
2019-10-07 11:51:25 +00:00
|
|
|
|
setSetting( 'onboarding', {
|
|
|
|
|
...getSetting( 'onboarding', {} ),
|
|
|
|
|
customLogo: !! themeMods.custom_logo,
|
|
|
|
|
} );
|
2019-09-02 03:45:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( 'notice' === step && isRequestSuccessful ) {
|
|
|
|
|
createNotice( 'success', __( 'Store notice updated sucessfully.', '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( {}, '/', {} ) );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 02:06:29 +00:00
|
|
|
|
importProducts() {
|
|
|
|
|
const { createNotice } = this.props;
|
|
|
|
|
this.setState( { isPending: true } );
|
|
|
|
|
|
2019-10-29 02:08:39 +00:00
|
|
|
|
recordEvent( 'tasklist_appearance_import_demo', {} );
|
|
|
|
|
|
2019-09-06 14:18:44 +00:00
|
|
|
|
apiFetch( {
|
|
|
|
|
path: `${ WC_ADMIN_NAMESPACE }/onboarding/tasks/import_sample_products`,
|
|
|
|
|
method: 'POST',
|
|
|
|
|
} )
|
2019-09-06 02:06:29 +00:00
|
|
|
|
.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' )
|
|
|
|
|
);
|
2019-10-07 11:51:25 +00:00
|
|
|
|
setSetting( 'onboarding', {
|
|
|
|
|
...getSetting( 'onboarding', {} ),
|
|
|
|
|
hasProducts: true,
|
|
|
|
|
} );
|
2019-09-06 02:06:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.setState( { isPending: false } );
|
|
|
|
|
this.completeStep();
|
|
|
|
|
} )
|
|
|
|
|
.catch( error => {
|
|
|
|
|
createNotice( 'error', error.message );
|
|
|
|
|
this.setState( { isPending: false } );
|
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-06 14:18:44 +00:00
|
|
|
|
createHomepage() {
|
|
|
|
|
const { createNotice } = this.props;
|
|
|
|
|
this.setState( { isPending: true } );
|
|
|
|
|
|
2019-10-07 20:27:34 +00:00
|
|
|
|
recordEvent( 'tasklist_appearance_create_homepage', { create_homepage: true } );
|
|
|
|
|
|
2019-11-12 18:15:55 +00:00
|
|
|
|
apiFetch( { path: '/wc-admin/onboarding/tasks/create_homepage', method: 'POST' } )
|
2019-09-06 14:18:44 +00:00
|
|
|
|
.then( response => {
|
|
|
|
|
createNotice( response.status, response.message );
|
|
|
|
|
|
|
|
|
|
this.setState( { isPending: false } );
|
|
|
|
|
if ( response.edit_post_link ) {
|
|
|
|
|
window.location = `${ response.edit_post_link }&wc_onboarding_active_task=homepage`;
|
|
|
|
|
}
|
|
|
|
|
} )
|
|
|
|
|
.catch( error => {
|
|
|
|
|
createNotice( 'error', error.message );
|
|
|
|
|
this.setState( { isPending: false } );
|
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-02 03:45:56 +00:00
|
|
|
|
updateLogo() {
|
|
|
|
|
const { options, themeMods, updateOptions } = this.props;
|
|
|
|
|
const { logo } = this.state;
|
2019-09-06 14:18:44 +00:00
|
|
|
|
const updateThemeMods = logo ? { ...themeMods, custom_logo: logo.id } : themeMods;
|
2019-09-02 03:45:56 +00:00
|
|
|
|
|
2019-10-07 20:27:34 +00:00
|
|
|
|
recordEvent( 'tasklist_appearance_upload_logo' );
|
|
|
|
|
|
2019-09-02 03:45:56 +00:00
|
|
|
|
updateOptions( {
|
2019-09-06 14:18:44 +00:00
|
|
|
|
[ `theme_mods_${ options.stylesheet }` ]: updateThemeMods,
|
2019-09-02 03:45:56 +00:00
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
updateNotice() {
|
|
|
|
|
const { updateOptions } = this.props;
|
|
|
|
|
const { storeNoticeText } = this.state;
|
|
|
|
|
|
2019-10-07 20:27:34 +00:00
|
|
|
|
recordEvent( 'tasklist_appearance_set_store_notice', {
|
|
|
|
|
added_text: Boolean( storeNoticeText.length ),
|
|
|
|
|
} );
|
|
|
|
|
|
2019-09-02 03:45:56 +00:00
|
|
|
|
updateOptions( {
|
|
|
|
|
woocommerce_demo_store: storeNoticeText.length ? 'yes' : 'no',
|
|
|
|
|
woocommerce_demo_store_notice: storeNoticeText,
|
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getSteps() {
|
2019-09-06 02:06:29 +00:00
|
|
|
|
const { isPending, logo, storeNoticeText } = this.state;
|
2019-09-02 03:45:56 +00:00
|
|
|
|
const { isRequesting } = this.props;
|
|
|
|
|
|
|
|
|
|
const steps = [
|
|
|
|
|
{
|
|
|
|
|
key: 'import',
|
|
|
|
|
label: __( 'Import demo products', 'woocommerce-admin' ),
|
|
|
|
|
description: __(
|
2019-10-29 18:15:36 +00:00
|
|
|
|
'We’ll add some products that will make it easier to see what your store looks like',
|
2019-09-02 03:45:56 +00:00
|
|
|
|
'woocommerce-admin'
|
|
|
|
|
),
|
|
|
|
|
content: (
|
|
|
|
|
<Fragment>
|
2019-09-06 02:06:29 +00:00
|
|
|
|
<Button onClick={ this.importProducts } isBusy={ isPending } isPrimary>
|
|
|
|
|
{ __( 'Import products', 'woocommerce-admin' ) }
|
|
|
|
|
</Button>
|
2019-09-02 03:45:56 +00:00
|
|
|
|
<Button onClick={ () => this.completeStep() }>
|
|
|
|
|
{ __( 'Skip', 'woocommerce-admin' ) }
|
|
|
|
|
</Button>
|
|
|
|
|
</Fragment>
|
|
|
|
|
),
|
2019-09-06 02:06:29 +00:00
|
|
|
|
visible: this.stepVisibility.import,
|
2019-09-02 03:45:56 +00:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'homepage',
|
|
|
|
|
label: __( 'Create a custom homepage', 'woocommerce-admin' ),
|
|
|
|
|
description: __(
|
|
|
|
|
'Create a new homepage and customize it to suit your needs',
|
|
|
|
|
'woocommerce-admin'
|
|
|
|
|
),
|
|
|
|
|
content: (
|
|
|
|
|
<Fragment>
|
2019-09-06 14:18:44 +00:00
|
|
|
|
<Button isPrimary onClick={ this.createHomepage }>
|
|
|
|
|
{ __( 'Create homepage', 'woocommerce-admin' ) }
|
|
|
|
|
</Button>
|
2019-10-07 20:27:34 +00:00
|
|
|
|
<Button
|
|
|
|
|
onClick={ () => {
|
|
|
|
|
recordEvent( 'tasklist_appearance_create_homepage', { create_homepage: false } );
|
|
|
|
|
this.completeStep();
|
|
|
|
|
} }
|
|
|
|
|
>
|
2019-09-02 03:45:56 +00:00
|
|
|
|
{ __( 'Skip', 'woocommerce-admin' ) }
|
|
|
|
|
</Button>
|
|
|
|
|
</Fragment>
|
|
|
|
|
),
|
2019-09-06 14:18:44 +00:00
|
|
|
|
visible: this.stepVisibility.homepage,
|
2019-09-02 03:45:56 +00:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'logo',
|
|
|
|
|
label: __( 'Upload a logo', 'woocommerce-admin' ),
|
|
|
|
|
description: __( 'Ensure your store is on-brand by adding your logo', 'woocommerce-admin' ),
|
|
|
|
|
content: (
|
|
|
|
|
<Fragment>
|
|
|
|
|
<ImageUpload image={ logo } onChange={ image => this.setState( { logo: image } ) } />
|
|
|
|
|
<Button onClick={ this.updateLogo } isBusy={ isRequesting } isPrimary>
|
|
|
|
|
{ __( 'Proceed', 'woocommerce-admin' ) }
|
|
|
|
|
</Button>
|
|
|
|
|
<Button onClick={ () => this.completeStep() }>
|
|
|
|
|
{ __( 'Skip', 'woocommerce-admin' ) }
|
|
|
|
|
</Button>
|
|
|
|
|
</Fragment>
|
|
|
|
|
),
|
2019-09-06 14:18:44 +00:00
|
|
|
|
visible: true,
|
2019-09-02 03:45:56 +00:00
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'notice',
|
|
|
|
|
label: __( 'Set a store notice', 'woocommerce-admin' ),
|
|
|
|
|
description: __(
|
|
|
|
|
'Optionally display a prominent notice across all pages of your store',
|
|
|
|
|
'woocommerce-admin'
|
|
|
|
|
),
|
|
|
|
|
content: (
|
|
|
|
|
<Fragment>
|
|
|
|
|
<TextControl
|
|
|
|
|
label={ __( 'Store notice text', 'woocommerce-admin' ) }
|
|
|
|
|
placeholder={ __( 'Store notice text', 'woocommerce-admin' ) }
|
|
|
|
|
value={ storeNoticeText }
|
|
|
|
|
onChange={ value => this.setState( { storeNoticeText: value } ) }
|
|
|
|
|
/>
|
|
|
|
|
<Button onClick={ this.updateNotice } isPrimary>
|
|
|
|
|
{ __( 'Complete task', 'woocommerce-admin' ) }
|
|
|
|
|
</Button>
|
|
|
|
|
</Fragment>
|
|
|
|
|
),
|
|
|
|
|
visible: true,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
return filter( steps, step => step.visible );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
2019-09-06 02:06:29 +00:00
|
|
|
|
const { isPending, stepIndex } = this.state;
|
2019-09-02 03:45:56 +00:00
|
|
|
|
const { isRequesting, hasErrors } = this.props;
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="woocommerce-task-appearance">
|
|
|
|
|
<Card className="is-narrow">
|
|
|
|
|
<Stepper
|
2019-09-06 02:06:29 +00:00
|
|
|
|
isPending={ ( isRequesting && ! hasErrors ) || isPending }
|
2019-09-02 03:45:56 +00:00
|
|
|
|
isVertical
|
|
|
|
|
currentStep={ this.getSteps()[ stepIndex ].key }
|
|
|
|
|
steps={ this.getSteps() }
|
|
|
|
|
/>
|
|
|
|
|
</Card>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default compose(
|
|
|
|
|
withSelect( select => {
|
2019-09-06 14:18:44 +00:00
|
|
|
|
const { getOptions, getOptionsError, isUpdateOptionsRequesting } = select( 'wc-api' );
|
2019-09-02 03:45:56 +00:00
|
|
|
|
|
|
|
|
|
const options = getOptions( [
|
|
|
|
|
'woocommerce_demo_store',
|
|
|
|
|
'woocommerce_demo_store_notice',
|
|
|
|
|
'stylesheet',
|
|
|
|
|
] );
|
|
|
|
|
const themeModsName = `theme_mods_${ options.stylesheet }`;
|
2019-09-06 14:18:44 +00:00
|
|
|
|
const themeOptions = options.stylesheet ? getOptions( [ themeModsName ] ) : null;
|
2019-09-02 03:45:56 +00:00
|
|
|
|
const themeMods =
|
|
|
|
|
themeOptions && themeOptions[ themeModsName ] ? themeOptions[ themeModsName ] : {};
|
|
|
|
|
|
|
|
|
|
const errors = [];
|
|
|
|
|
const uploadLogoError = getOptionsError( [ themeModsName ] );
|
|
|
|
|
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 =
|
2019-09-06 14:18:44 +00:00
|
|
|
|
Boolean( isUpdateOptionsRequesting( [ themeModsName ] ) ) ||
|
2019-09-02 03:45:56 +00:00
|
|
|
|
Boolean(
|
2019-09-06 14:18:44 +00:00
|
|
|
|
isUpdateOptionsRequesting( [ 'woocommerce_demo_store', 'woocommerce_demo_store_notice' ] )
|
2019-09-02 03:45:56 +00:00
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return { errors, getOptionsError, hasErrors, isRequesting, options, themeMods };
|
|
|
|
|
} ),
|
|
|
|
|
withDispatch( dispatch => {
|
|
|
|
|
const { createNotice } = dispatch( 'core/notices' );
|
|
|
|
|
const { updateOptions } = dispatch( 'wc-api' );
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
createNotice,
|
|
|
|
|
updateOptions,
|
|
|
|
|
};
|
|
|
|
|
} )
|
|
|
|
|
)( Appearance );
|