2021-09-21 19:33:44 +00:00
|
|
|
|
/**
|
|
|
|
|
* External dependencies
|
|
|
|
|
*/
|
|
|
|
|
import { __ } from '@wordpress/i18n';
|
|
|
|
|
import apiFetch from '@wordpress/api-fetch';
|
|
|
|
|
import { Button, Card, CardBody } from '@wordpress/components';
|
|
|
|
|
import { Component, Fragment } from '@wordpress/element';
|
|
|
|
|
import { compose } from '@wordpress/compose';
|
|
|
|
|
import { filter } from 'lodash';
|
|
|
|
|
import { withDispatch, withSelect } from '@wordpress/data';
|
|
|
|
|
|
|
|
|
|
import { Stepper, TextControl, ImageUpload } from '@woocommerce/components';
|
|
|
|
|
import {
|
|
|
|
|
OPTIONS_STORE_NAME,
|
|
|
|
|
ONBOARDING_STORE_NAME,
|
|
|
|
|
WC_ADMIN_NAMESPACE,
|
|
|
|
|
} from '@woocommerce/data';
|
|
|
|
|
import { queueRecordEvent, recordEvent } from '@woocommerce/tracks';
|
|
|
|
|
import { registerPlugin } from '@wordpress/plugins';
|
|
|
|
|
import { WooOnboardingTask } from '@woocommerce/onboarding';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Internal dependencies
|
|
|
|
|
*/
|
|
|
|
|
class Appearance extends Component {
|
|
|
|
|
constructor( props ) {
|
|
|
|
|
super( props );
|
2021-11-09 12:42:33 +00:00
|
|
|
|
const { hasHomepage, hasProducts } = props.task.additionalData;
|
2021-09-21 19:33:44 +00:00
|
|
|
|
|
|
|
|
|
this.stepVisibility = {
|
|
|
|
|
homepage: ! hasHomepage,
|
|
|
|
|
import: ! hasProducts,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.state = {
|
|
|
|
|
isDirty: false,
|
|
|
|
|
isPending: false,
|
|
|
|
|
logo: null,
|
|
|
|
|
stepIndex: 0,
|
|
|
|
|
isUpdatingLogo: false,
|
|
|
|
|
isUpdatingNotice: false,
|
|
|
|
|
storeNoticeText: props.demoStoreNotice || '',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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() {
|
2021-11-09 12:42:33 +00:00
|
|
|
|
const { themeMods } = this.props.task.additionalData;
|
2021-09-21 19:33:44 +00:00
|
|
|
|
|
|
|
|
|
if ( themeMods && 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 */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
componentDidUpdate( prevProps ) {
|
|
|
|
|
const { isPending, logo } = this.state;
|
|
|
|
|
const { demoStoreNotice } = this.props;
|
|
|
|
|
|
|
|
|
|
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 (
|
|
|
|
|
demoStoreNotice &&
|
|
|
|
|
prevProps.demoStoreNotice !== demoStoreNotice
|
|
|
|
|
) {
|
|
|
|
|
/* eslint-disable react/no-did-update-set-state */
|
|
|
|
|
this.setState( {
|
|
|
|
|
storeNoticeText: demoStoreNotice,
|
|
|
|
|
} );
|
|
|
|
|
/* eslint-enable react/no-did-update-set-state */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-08 21:01:12 +00:00
|
|
|
|
async completeStep() {
|
2021-09-21 19:33:44 +00:00
|
|
|
|
const { stepIndex } = this.state;
|
2021-10-08 21:01:12 +00:00
|
|
|
|
const { actionTask, onComplete } = this.props;
|
2021-09-21 19:33:44 +00:00
|
|
|
|
const nextStep = this.getSteps()[ stepIndex + 1 ];
|
|
|
|
|
|
|
|
|
|
if ( nextStep ) {
|
|
|
|
|
this.setState( { stepIndex: stepIndex + 1 } );
|
|
|
|
|
} else {
|
2021-10-08 21:01:12 +00:00
|
|
|
|
this.setState( { isPending: true } );
|
|
|
|
|
await actionTask( 'appearance' );
|
2021-10-01 19:53:22 +00:00
|
|
|
|
onComplete();
|
2021-09-21 19:33:44 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
importProducts() {
|
2021-11-09 12:42:33 +00:00
|
|
|
|
const { createNotice } = this.props;
|
2021-09-21 19:33:44 +00:00
|
|
|
|
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 sample products',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
'woocommerce'
|
2021-09-21 19:33:44 +00:00
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
createNotice(
|
|
|
|
|
'success',
|
|
|
|
|
__(
|
|
|
|
|
'All sample products have been imported',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
'woocommerce'
|
2021-09-21 19:33:44 +00:00
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.setState( { isPending: false } );
|
|
|
|
|
this.completeStep();
|
|
|
|
|
} )
|
2022-01-25 19:06:38 +00:00
|
|
|
|
.catch( ( { message } ) => {
|
|
|
|
|
createNotice(
|
|
|
|
|
'error',
|
|
|
|
|
message ||
|
|
|
|
|
__(
|
|
|
|
|
'There was an error importing the sample products',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
'woocommerce'
|
2022-01-25 19:06:38 +00:00
|
|
|
|
),
|
|
|
|
|
{ __unstableHTML: true }
|
|
|
|
|
);
|
2021-09-21 19:33:44 +00:00
|
|
|
|
this.setState( { isPending: false } );
|
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
createHomepage() {
|
2021-11-09 12:42:33 +00:00
|
|
|
|
const { createNotice } = this.props;
|
2021-09-21 19:33:44 +00:00
|
|
|
|
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
|
|
|
|
|
? [
|
|
|
|
|
{
|
2022-03-30 09:00:04 +00:00
|
|
|
|
label: __( 'Customize', 'woocommerce' ),
|
2021-09-21 19:33:44 +00:00
|
|
|
|
onClick: () => {
|
|
|
|
|
queueRecordEvent(
|
|
|
|
|
'tasklist_appearance_customize_homepage',
|
|
|
|
|
{}
|
|
|
|
|
);
|
2021-10-06 20:48:28 +00:00
|
|
|
|
window.location = `${ response.edit_post_link }&wc_onboarding_active_task=appearance`;
|
2021-09-21 19:33:44 +00:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
: null,
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
this.setState( { isPending: false } );
|
|
|
|
|
this.completeStep();
|
|
|
|
|
} )
|
|
|
|
|
.catch( ( error ) => {
|
|
|
|
|
createNotice( 'error', error.message );
|
|
|
|
|
this.setState( { isPending: false } );
|
|
|
|
|
} );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async updateLogo() {
|
2021-11-09 12:42:33 +00:00
|
|
|
|
const { createNotice, task, updateOptions } = this.props;
|
|
|
|
|
const { stylesheet, themeMods } = task.additionalData;
|
2021-09-21 19:33:44 +00:00
|
|
|
|
const { logo } = this.state;
|
|
|
|
|
const updatedThemeMods = {
|
|
|
|
|
...themeMods,
|
|
|
|
|
custom_logo: logo ? logo.id : null,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
recordEvent( 'tasklist_appearance_upload_logo' );
|
|
|
|
|
|
|
|
|
|
this.setState( { isUpdatingLogo: true } );
|
|
|
|
|
const update = await updateOptions( {
|
|
|
|
|
[ `theme_mods_${ stylesheet }` ]: updatedThemeMods,
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
if ( update.success ) {
|
|
|
|
|
this.setState( { isUpdatingLogo: false } );
|
|
|
|
|
createNotice(
|
|
|
|
|
'success',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
__( 'Store logo updated sucessfully', 'woocommerce' )
|
2021-09-21 19:33:44 +00:00
|
|
|
|
);
|
|
|
|
|
this.completeStep();
|
|
|
|
|
} else {
|
|
|
|
|
createNotice( 'error', update.message );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async updateNotice() {
|
2021-11-09 12:42:33 +00:00
|
|
|
|
const { createNotice, updateOptions } = this.props;
|
2021-09-21 19:33:44 +00:00
|
|
|
|
const { storeNoticeText } = this.state;
|
|
|
|
|
|
|
|
|
|
recordEvent( 'tasklist_appearance_set_store_notice', {
|
|
|
|
|
added_text: Boolean( storeNoticeText.length ),
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
this.setState( { isUpdatingNotice: true } );
|
|
|
|
|
const update = await updateOptions( {
|
|
|
|
|
woocommerce_demo_store: storeNoticeText.length ? 'yes' : 'no',
|
|
|
|
|
woocommerce_demo_store_notice: storeNoticeText,
|
|
|
|
|
} );
|
|
|
|
|
|
|
|
|
|
if ( update.success ) {
|
|
|
|
|
this.setState( { isUpdatingNotice: false } );
|
|
|
|
|
createNotice(
|
|
|
|
|
'success',
|
|
|
|
|
__(
|
|
|
|
|
"🎨 Your store is looking great! Don't forget to continue personalizing it",
|
2022-03-30 09:00:04 +00:00
|
|
|
|
'woocommerce'
|
2021-09-21 19:33:44 +00:00
|
|
|
|
)
|
|
|
|
|
);
|
|
|
|
|
this.completeStep();
|
|
|
|
|
} else {
|
|
|
|
|
createNotice( 'error', update.message );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getSteps() {
|
2022-06-21 08:37:34 +00:00
|
|
|
|
const { isDirty, isPending, logo, storeNoticeText, isUpdatingLogo } =
|
|
|
|
|
this.state;
|
2021-09-21 19:33:44 +00:00
|
|
|
|
|
|
|
|
|
const steps = [
|
|
|
|
|
{
|
|
|
|
|
key: 'import',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
label: __( 'Import sample products', 'woocommerce' ),
|
2021-09-21 19:33:44 +00:00
|
|
|
|
description: __(
|
|
|
|
|
'We’ll add some products that will make it easier to see what your store looks like',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
'woocommerce'
|
2021-09-21 19:33:44 +00:00
|
|
|
|
),
|
|
|
|
|
content: (
|
|
|
|
|
<Fragment>
|
|
|
|
|
<Button
|
|
|
|
|
onClick={ this.importProducts }
|
|
|
|
|
isBusy={ isPending }
|
|
|
|
|
isPrimary
|
|
|
|
|
>
|
2022-03-30 09:00:04 +00:00
|
|
|
|
{ __( 'Import products', 'woocommerce' ) }
|
2021-09-21 19:33:44 +00:00
|
|
|
|
</Button>
|
|
|
|
|
<Button onClick={ () => this.completeStep() }>
|
2022-03-30 09:00:04 +00:00
|
|
|
|
{ __( 'Skip', 'woocommerce' ) }
|
2021-09-21 19:33:44 +00:00
|
|
|
|
</Button>
|
|
|
|
|
</Fragment>
|
|
|
|
|
),
|
|
|
|
|
visible: this.stepVisibility.import,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'homepage',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
label: __( 'Create a custom homepage', 'woocommerce' ),
|
2021-09-21 19:33:44 +00:00
|
|
|
|
description: __(
|
|
|
|
|
'Create a new homepage and customize it to suit your needs',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
'woocommerce'
|
2021-09-21 19:33:44 +00:00
|
|
|
|
),
|
|
|
|
|
content: (
|
|
|
|
|
<Fragment>
|
|
|
|
|
<Button
|
|
|
|
|
isPrimary
|
|
|
|
|
isBusy={ isPending }
|
|
|
|
|
onClick={ this.createHomepage }
|
|
|
|
|
>
|
2022-03-30 09:00:04 +00:00
|
|
|
|
{ __( 'Create homepage', 'woocommerce' ) }
|
2021-09-21 19:33:44 +00:00
|
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
isTertiary
|
|
|
|
|
onClick={ () => {
|
|
|
|
|
recordEvent(
|
|
|
|
|
'tasklist_appearance_create_homepage',
|
|
|
|
|
{ create_homepage: false }
|
|
|
|
|
);
|
|
|
|
|
this.completeStep();
|
|
|
|
|
} }
|
|
|
|
|
>
|
2022-03-30 09:00:04 +00:00
|
|
|
|
{ __( 'Skip', 'woocommerce' ) }
|
2021-09-21 19:33:44 +00:00
|
|
|
|
</Button>
|
|
|
|
|
</Fragment>
|
|
|
|
|
),
|
|
|
|
|
visible: this.stepVisibility.homepage,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'logo',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
label: __( 'Upload a logo', 'woocommerce' ),
|
2021-09-21 19:33:44 +00:00
|
|
|
|
description: __(
|
|
|
|
|
'Ensure your store is on-brand by adding your logo',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
'woocommerce'
|
2021-09-21 19:33:44 +00:00
|
|
|
|
),
|
|
|
|
|
content: isPending ? null : (
|
|
|
|
|
<Fragment>
|
|
|
|
|
<ImageUpload
|
|
|
|
|
image={ logo }
|
|
|
|
|
onChange={ ( image ) =>
|
|
|
|
|
this.setState( { isDirty: true, logo: image } )
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Button
|
|
|
|
|
disabled={ ! logo && ! isDirty }
|
|
|
|
|
onClick={ this.updateLogo }
|
|
|
|
|
isBusy={ isUpdatingLogo }
|
|
|
|
|
isPrimary
|
|
|
|
|
>
|
2022-03-30 09:00:04 +00:00
|
|
|
|
{ __( 'Proceed', 'woocommerce' ) }
|
2021-09-21 19:33:44 +00:00
|
|
|
|
</Button>
|
|
|
|
|
<Button
|
|
|
|
|
isTertiary
|
|
|
|
|
onClick={ () => this.completeStep() }
|
|
|
|
|
>
|
2022-03-30 09:00:04 +00:00
|
|
|
|
{ __( 'Skip', 'woocommerce' ) }
|
2021-09-21 19:33:44 +00:00
|
|
|
|
</Button>
|
|
|
|
|
</Fragment>
|
|
|
|
|
),
|
|
|
|
|
visible: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
key: 'notice',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
label: __( 'Set a store notice', 'woocommerce' ),
|
2021-09-21 19:33:44 +00:00
|
|
|
|
description: __(
|
|
|
|
|
'Optionally display a prominent notice across all pages of your store',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
'woocommerce'
|
2021-09-21 19:33:44 +00:00
|
|
|
|
),
|
|
|
|
|
content: (
|
|
|
|
|
<Fragment>
|
|
|
|
|
<TextControl
|
2022-03-30 09:00:04 +00:00
|
|
|
|
label={ __( 'Store notice text', 'woocommerce' ) }
|
2021-09-21 19:33:44 +00:00
|
|
|
|
placeholder={ __(
|
|
|
|
|
'Store notice text',
|
2022-03-30 09:00:04 +00:00
|
|
|
|
'woocommerce'
|
2021-09-21 19:33:44 +00:00
|
|
|
|
) }
|
|
|
|
|
value={ storeNoticeText }
|
|
|
|
|
onChange={ ( value ) =>
|
|
|
|
|
this.setState( { storeNoticeText: value } )
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
<Button onClick={ this.updateNotice } isPrimary>
|
2022-03-30 09:00:04 +00:00
|
|
|
|
{ __( 'Complete task', 'woocommerce' ) }
|
2021-09-21 19:33:44 +00:00
|
|
|
|
</Button>
|
|
|
|
|
</Fragment>
|
|
|
|
|
),
|
|
|
|
|
visible: true,
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
return filter( steps, ( step ) => step.visible );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render() {
|
2022-06-21 08:37:34 +00:00
|
|
|
|
const { isPending, stepIndex, isUpdatingLogo, isUpdatingNotice } =
|
|
|
|
|
this.state;
|
2021-09-21 19:33:44 +00:00
|
|
|
|
const currentStep = this.getSteps()[ stepIndex ].key;
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="woocommerce-task-appearance">
|
|
|
|
|
<Card className="woocommerce-task-card">
|
|
|
|
|
<CardBody>
|
|
|
|
|
<Stepper
|
|
|
|
|
isPending={
|
|
|
|
|
isUpdatingNotice || isUpdatingLogo || isPending
|
|
|
|
|
}
|
|
|
|
|
isVertical
|
|
|
|
|
currentStep={ currentStep }
|
|
|
|
|
steps={ this.getSteps() }
|
|
|
|
|
/>
|
|
|
|
|
</CardBody>
|
|
|
|
|
</Card>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const AppearanceWrapper = compose(
|
|
|
|
|
withSelect( ( select ) => {
|
|
|
|
|
const { getOption } = select( OPTIONS_STORE_NAME );
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
demoStoreNotice: getOption( 'woocommerce_demo_store_notice' ),
|
|
|
|
|
};
|
|
|
|
|
} ),
|
|
|
|
|
withDispatch( ( dispatch ) => {
|
|
|
|
|
const { createNotice } = dispatch( 'core/notices' );
|
|
|
|
|
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
2021-11-09 12:42:33 +00:00
|
|
|
|
const { actionTask } = dispatch( ONBOARDING_STORE_NAME );
|
2021-09-21 19:33:44 +00:00
|
|
|
|
|
|
|
|
|
return {
|
2021-10-08 21:01:12 +00:00
|
|
|
|
actionTask,
|
2021-09-21 19:33:44 +00:00
|
|
|
|
createNotice,
|
|
|
|
|
updateOptions,
|
|
|
|
|
};
|
|
|
|
|
} )
|
|
|
|
|
)( Appearance );
|
|
|
|
|
|
|
|
|
|
registerPlugin( 'wc-admin-onboarding-task-appearance', {
|
|
|
|
|
scope: 'woocommerce-tasks',
|
|
|
|
|
render: () => (
|
|
|
|
|
<WooOnboardingTask id="appearance">
|
2021-11-09 12:42:33 +00:00
|
|
|
|
{ ( { onComplete, task } ) => (
|
|
|
|
|
<AppearanceWrapper onComplete={ onComplete } task={ task } />
|
2021-10-01 19:53:22 +00:00
|
|
|
|
) }
|
2021-09-21 19:33:44 +00:00
|
|
|
|
</WooOnboardingTask>
|
|
|
|
|
),
|
|
|
|
|
} );
|