Onboarding: Add "Customize Appearance" task (https://github.com/woocommerce/woocommerce-admin/pull/2857)
* Add initial Customize Appearance task * Add options wc endpoint * Add wc-api specs to manage options
This commit is contained in:
parent
e156605bfa
commit
7bce0b710f
|
@ -4,7 +4,7 @@
|
|||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Component, Fragment } from '@wordpress/element';
|
||||
import { filter, noop } from 'lodash';
|
||||
import { filter } from 'lodash';
|
||||
import { compose } from '@wordpress/compose';
|
||||
|
||||
/**
|
||||
|
@ -17,6 +17,7 @@ import { updateQueryString } from '@woocommerce/navigation';
|
|||
* Internal depdencies
|
||||
*/
|
||||
import './style.scss';
|
||||
import Appearance from './tasks/appearance';
|
||||
import Connect from './tasks/connect';
|
||||
import Products from './tasks/products';
|
||||
import Shipping from './tasks/shipping';
|
||||
|
@ -72,12 +73,13 @@ class TaskDashboard extends Component {
|
|||
visible: true,
|
||||
},
|
||||
{
|
||||
key: 'personalize-store',
|
||||
key: 'appearance',
|
||||
title: __( 'Personalize your store', 'woocommerce-admin' ),
|
||||
content: __( 'Create a custom homepage and upload your logo', 'wooocommerce-admin' ),
|
||||
before: <i className="material-icons-outlined">palette</i>,
|
||||
after: <i className="material-icons-outlined">chevron_right</i>,
|
||||
onClick: noop,
|
||||
onClick: () => updateQueryString( { task: 'appearance' } ),
|
||||
container: <Appearance />,
|
||||
visible: true,
|
||||
},
|
||||
{
|
||||
|
|
|
@ -225,3 +225,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-task-appearance {
|
||||
.muriel-image-upload {
|
||||
margin-bottom: $gap-smallest;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,254 @@
|
|||
/** @format */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Button, ImageUpload, TextControl } from 'newspack-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 } from '@woocommerce/components';
|
||||
import { getHistory, getNewPath } from '@woocommerce/navigation';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import withSelect from 'wc-api/with-select';
|
||||
|
||||
class Appearance extends Component {
|
||||
constructor( props ) {
|
||||
super( props );
|
||||
|
||||
this.state = {
|
||||
logo: null,
|
||||
stepIndex: 0,
|
||||
storeNoticeText: props.options.woocommerce_demo_store_notice || '',
|
||||
};
|
||||
|
||||
this.completeStep = this.completeStep.bind( this );
|
||||
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();
|
||||
}
|
||||
|
||||
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( {}, '/', {} ) );
|
||||
}
|
||||
}
|
||||
|
||||
updateLogo() {
|
||||
const { options, themeMods, updateOptions } = this.props;
|
||||
const { logo } = this.state;
|
||||
|
||||
updateOptions( {
|
||||
[ `theme_mods_${ options.stylesheet }` ]: { ...themeMods, custom_logo: logo.id },
|
||||
} );
|
||||
}
|
||||
|
||||
updateNotice() {
|
||||
const { updateOptions } = this.props;
|
||||
const { storeNoticeText } = this.state;
|
||||
|
||||
updateOptions( {
|
||||
woocommerce_demo_store: storeNoticeText.length ? 'yes' : 'no',
|
||||
woocommerce_demo_store_notice: storeNoticeText,
|
||||
} );
|
||||
}
|
||||
|
||||
getSteps() {
|
||||
const { 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 it will make it easier to see what your store looks like.',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: (
|
||||
<Fragment>
|
||||
<Button isPrimary>{ __( 'Import products', 'woocommerce-admin' ) }</Button>
|
||||
<Button onClick={ () => this.completeStep() }>
|
||||
{ __( 'Skip', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
</Fragment>
|
||||
),
|
||||
visible: true,
|
||||
},
|
||||
{
|
||||
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>
|
||||
<Button isPrimary>{ __( 'Create homepage', 'woocommerce-admin' ) }</Button>
|
||||
<Button onClick={ () => this.completeStep() }>
|
||||
{ __( 'Skip', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
</Fragment>
|
||||
),
|
||||
visible: true,
|
||||
},
|
||||
{
|
||||
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>
|
||||
),
|
||||
visible: ! wcSettings.onboarding.customLogo,
|
||||
},
|
||||
{
|
||||
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() {
|
||||
const { stepIndex } = this.state;
|
||||
const { isRequesting, hasErrors } = this.props;
|
||||
|
||||
return (
|
||||
<div className="woocommerce-task-appearance">
|
||||
<Card className="is-narrow">
|
||||
<Stepper
|
||||
isPending={ isRequesting && ! hasErrors }
|
||||
isVertical
|
||||
currentStep={ this.getSteps()[ stepIndex ].key }
|
||||
steps={ this.getSteps() }
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withSelect( select => {
|
||||
const { getOptions, getOptionsError, isOptionsRequesting } = select( 'wc-api' );
|
||||
|
||||
const options = getOptions( [
|
||||
'woocommerce_demo_store',
|
||||
'woocommerce_demo_store_notice',
|
||||
'stylesheet',
|
||||
] );
|
||||
const themeModsName = `theme_mods_${ options.stylesheet }`;
|
||||
const themeOptions =
|
||||
options.stylesheet && ! wcSettings.onboarding.customLogo
|
||||
? getOptions( [ themeModsName ] )
|
||||
: null;
|
||||
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 =
|
||||
Boolean( isOptionsRequesting( [ themeModsName ] ) ) ||
|
||||
Boolean(
|
||||
isOptionsRequesting( [ 'woocommerce_demo_store', 'woocommerce_demo_store_notice' ] )
|
||||
);
|
||||
|
||||
return { errors, getOptionsError, hasErrors, isRequesting, options, themeMods };
|
||||
} ),
|
||||
withDispatch( dispatch => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
|
||||
return {
|
||||
createNotice,
|
||||
updateOptions,
|
||||
};
|
||||
} )
|
||||
)( Appearance );
|
|
@ -4,7 +4,9 @@
|
|||
*/
|
||||
import { MINUTE } from '@fresh-data/framework';
|
||||
|
||||
export const JETPACK_NAMESPACE = '/jetpack/v4';
|
||||
export const NAMESPACE = '/wc/v4';
|
||||
export const WC_ADMIN_NAMESPACE = '/wc-admin/v1';
|
||||
|
||||
export const DEFAULT_REQUIREMENT = {
|
||||
timeout: 1 * MINUTE,
|
||||
|
|
|
@ -4,12 +4,6 @@
|
|||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Onboarding namespace.
|
||||
*/
|
||||
export const NAMESPACE = '/wc-admin/v1';
|
||||
export const JETPACK_NAMESPACE = '/jetpack/v4';
|
||||
|
||||
/**
|
||||
* Plugin slugs and names as key/value pairs.
|
||||
*/
|
||||
|
|
|
@ -10,7 +10,8 @@ import apiFetch from '@wordpress/api-fetch';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { getResourceName } from '../utils';
|
||||
import { JETPACK_NAMESPACE, NAMESPACE, pluginNames } from './constants';
|
||||
import { JETPACK_NAMESPACE, WC_ADMIN_NAMESPACE } from '../constants';
|
||||
import { pluginNames } from './constants';
|
||||
|
||||
function read( resourceNames, fetch = apiFetch ) {
|
||||
return [
|
||||
|
@ -33,7 +34,7 @@ function readProfileItems( resourceNames, fetch ) {
|
|||
const resourceName = 'onboarding-profile';
|
||||
|
||||
if ( resourceNames.includes( resourceName ) ) {
|
||||
const url = NAMESPACE + '/onboarding/profile';
|
||||
const url = WC_ADMIN_NAMESPACE + '/onboarding/profile';
|
||||
|
||||
return [
|
||||
fetch( { path: url } )
|
||||
|
@ -51,7 +52,7 @@ function updateProfileItems( resourceNames, data, fetch ) {
|
|||
const resourceName = 'onboarding-profile';
|
||||
|
||||
if ( resourceNames.includes( resourceName ) ) {
|
||||
const url = NAMESPACE + '/onboarding/profile';
|
||||
const url = WC_ADMIN_NAMESPACE + '/onboarding/profile';
|
||||
|
||||
return [
|
||||
fetch( {
|
||||
|
@ -103,7 +104,7 @@ function profileItemToResource( items ) {
|
|||
function readActivePlugins( resourceNames, fetch ) {
|
||||
const resourceName = 'active-plugins';
|
||||
if ( resourceNames.includes( resourceName ) ) {
|
||||
const url = NAMESPACE + '/onboarding/plugins/active';
|
||||
const url = WC_ADMIN_NAMESPACE + '/onboarding/plugins/active';
|
||||
|
||||
return [
|
||||
fetch( { path: url } )
|
||||
|
@ -131,7 +132,7 @@ function activatePlugins( resourceNames, data, fetch ) {
|
|||
const resourceName = 'plugin-activate';
|
||||
if ( resourceNames.includes( resourceName ) ) {
|
||||
const plugins = data[ resourceName ];
|
||||
const url = NAMESPACE + '/onboarding/plugins/activate';
|
||||
const url = WC_ADMIN_NAMESPACE + '/onboarding/plugins/activate';
|
||||
return [
|
||||
fetch( {
|
||||
path: url,
|
||||
|
@ -197,7 +198,7 @@ function readJetpackConnectUrl( resourceNames, fetch ) {
|
|||
const resourceName = 'jetpack-connect-url';
|
||||
|
||||
if ( resourceNames.includes( resourceName ) ) {
|
||||
const url = NAMESPACE + '/onboarding/plugins/connect-jetpack';
|
||||
const url = WC_ADMIN_NAMESPACE + '/onboarding/plugins/connect-jetpack';
|
||||
|
||||
return [
|
||||
fetch( {
|
||||
|
@ -245,7 +246,7 @@ function installPlugins( resourceNames, data, fetch ) {
|
|||
|
||||
return plugins.map( async plugin => {
|
||||
return fetch( {
|
||||
path: `${ NAMESPACE }/onboarding/plugins/install`,
|
||||
path: `${ WC_ADMIN_NAMESPACE }/onboarding/plugins/install`,
|
||||
method: 'POST',
|
||||
data: {
|
||||
plugin,
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/** @format */
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import operations from './operations';
|
||||
import selectors from './selectors';
|
||||
import mutations from './mutations';
|
||||
|
||||
export default {
|
||||
operations,
|
||||
selectors,
|
||||
mutations,
|
||||
};
|
|
@ -0,0 +1,15 @@
|
|||
/** @format */
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getResourceName } from '../utils';
|
||||
|
||||
const updateOptions = operations => options => {
|
||||
const resourceName = getResourceName( 'options', Object.keys( options ) );
|
||||
operations.update( [ resourceName ], { [ resourceName ]: options } );
|
||||
};
|
||||
|
||||
export default {
|
||||
updateOptions,
|
||||
};
|
|
@ -0,0 +1,76 @@
|
|||
/** @format */
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import apiFetch from '@wordpress/api-fetch';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getResourceIdentifier, getResourceName } from '../utils';
|
||||
import { WC_ADMIN_NAMESPACE } from '../constants';
|
||||
|
||||
function read( resourceNames, fetch = apiFetch ) {
|
||||
return [ ...readOptions( resourceNames, fetch ) ];
|
||||
}
|
||||
|
||||
function update( resourceNames, data, fetch = apiFetch ) {
|
||||
return [ ...updateOptions( resourceNames, data, fetch ) ];
|
||||
}
|
||||
|
||||
function readOptions( resourceNames, fetch ) {
|
||||
const filteredNames = resourceNames.filter( name => {
|
||||
return name.startsWith( 'options' );
|
||||
} );
|
||||
|
||||
return filteredNames.map( async resourceName => {
|
||||
const optionNames = getResourceIdentifier( resourceName );
|
||||
const url = WC_ADMIN_NAMESPACE + '/options?options=' + optionNames.join( ',' );
|
||||
|
||||
return fetch( { path: url } )
|
||||
.then( optionsToResource )
|
||||
.catch( error => {
|
||||
return { [ resourceName ]: { error: String( error.message ) } };
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
function updateOptions( resourceNames, data, fetch ) {
|
||||
const url = WC_ADMIN_NAMESPACE + '/options';
|
||||
|
||||
const filteredNames = resourceNames.filter( name => {
|
||||
return name.startsWith( 'options' );
|
||||
} );
|
||||
|
||||
return filteredNames.map( async resourceName => {
|
||||
return fetch( { path: url, method: 'POST', data: data[ resourceName ] } )
|
||||
.then( () => optionsToResource( data[ resourceName ] ) )
|
||||
.catch( error => {
|
||||
return { [ resourceName ]: { error } };
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
function optionsToResource( options ) {
|
||||
const optionNames = Object.keys( options );
|
||||
const resourceName = getResourceName( 'options', optionNames );
|
||||
const resources = {};
|
||||
|
||||
optionNames.forEach(
|
||||
optionName =>
|
||||
( resources[ getResourceName( 'options', optionName ) ] = { data: options[ optionName ] } )
|
||||
);
|
||||
|
||||
return {
|
||||
[ resourceName ]: {
|
||||
data: optionNames,
|
||||
},
|
||||
...resources,
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
read,
|
||||
update,
|
||||
};
|
|
@ -0,0 +1,48 @@
|
|||
/** @format */
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { isNil } from 'lodash';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { DEFAULT_REQUIREMENT } from '../constants';
|
||||
import { getResourceName } from '../utils';
|
||||
|
||||
const getOptions = ( getResource, requireResource ) => (
|
||||
optionNames,
|
||||
requirement = DEFAULT_REQUIREMENT
|
||||
) => {
|
||||
const resourceName = getResourceName( 'options', optionNames );
|
||||
const options = {};
|
||||
|
||||
const names = requireResource( requirement, resourceName ).data || [];
|
||||
|
||||
names.forEach( name => {
|
||||
options[ name ] = getResource( getResourceName( 'options', name ) ).data;
|
||||
} );
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
const getOptionsError = getResource => optionNames => {
|
||||
return getResource( getResourceName( 'options', optionNames ) ).error;
|
||||
};
|
||||
|
||||
const isOptionsRequesting = getResource => optionNames => {
|
||||
const { lastReceived, lastRequested } = getResource( getResourceName( 'options', optionNames ) );
|
||||
|
||||
if ( ! isNil( lastRequested ) && isNil( lastReceived ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return lastRequested > lastReceived;
|
||||
};
|
||||
|
||||
export default {
|
||||
getOptions,
|
||||
getOptionsError,
|
||||
isOptionsRequesting,
|
||||
};
|
|
@ -7,6 +7,7 @@ import items from './items';
|
|||
import imports from './imports';
|
||||
import notes from './notes';
|
||||
import onboarding from './onboarding';
|
||||
import options from './options';
|
||||
import reportItems from './reports/items';
|
||||
import reportStats from './reports/stats';
|
||||
import reviews from './reviews';
|
||||
|
@ -20,6 +21,7 @@ function createWcApiSpec() {
|
|||
...items.mutations,
|
||||
...notes.mutations,
|
||||
...onboarding.mutations,
|
||||
...options.mutations,
|
||||
...settings.mutations,
|
||||
...user.mutations,
|
||||
},
|
||||
|
@ -28,6 +30,7 @@ function createWcApiSpec() {
|
|||
...items.selectors,
|
||||
...notes.selectors,
|
||||
...onboarding.selectors,
|
||||
...options.selectors,
|
||||
...reportItems.selectors,
|
||||
...reportStats.selectors,
|
||||
...reviews.selectors,
|
||||
|
@ -46,6 +49,7 @@ function createWcApiSpec() {
|
|||
...items.operations.read( resourceNames ),
|
||||
...notes.operations.read( resourceNames ),
|
||||
...onboarding.operations.read( resourceNames ),
|
||||
...options.operations.read( resourceNames ),
|
||||
...reportItems.operations.read( resourceNames ),
|
||||
...reportStats.operations.read( resourceNames ),
|
||||
...reviews.operations.read( resourceNames ),
|
||||
|
@ -58,6 +62,7 @@ function createWcApiSpec() {
|
|||
...items.operations.update( resourceNames, data ),
|
||||
...notes.operations.update( resourceNames, data ),
|
||||
...onboarding.operations.update( resourceNames, data ),
|
||||
...options.operations.update( resourceNames, data ),
|
||||
...settings.operations.update( resourceNames, data ),
|
||||
...user.operations.update( resourceNames, data ),
|
||||
];
|
||||
|
|
|
@ -43,6 +43,7 @@ class Init {
|
|||
'Automattic\WooCommerce\Admin\API\DataCountries',
|
||||
'Automattic\WooCommerce\Admin\API\DataDownloadIPs',
|
||||
'Automattic\WooCommerce\Admin\API\Leaderboards',
|
||||
'Automattic\WooCommerce\Admin\API\Options',
|
||||
'Automattic\WooCommerce\Admin\API\Orders',
|
||||
'Automattic\WooCommerce\Admin\API\Products',
|
||||
'Automattic\WooCommerce\Admin\API\ProductCategories',
|
||||
|
|
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
/**
|
||||
* REST API Options Controller
|
||||
*
|
||||
* Handles requests to get and update options in the wp_options table.
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
*/
|
||||
|
||||
namespace Automattic\WooCommerce\Admin\API;
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Options Controller.
|
||||
*
|
||||
* @package WooCommerce Admin/API
|
||||
* @extends WC_REST_Data_Controller
|
||||
*/
|
||||
class Options extends \WC_REST_Data_Controller {
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc-admin/v1';
|
||||
|
||||
/**
|
||||
* Route base.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'options';
|
||||
|
||||
/**
|
||||
* Register routes.
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_options' ),
|
||||
'permission_callback' => array( $this, 'update_item_permissions_check' ),
|
||||
),
|
||||
'schema' => array( $this, 'get_item_schema' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'update_options' ),
|
||||
'permission_callback' => array( $this, 'update_item_permissions_check' ),
|
||||
),
|
||||
'schema' => array( $this, 'get_item_schema' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given request has access to manage options.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_Error|boolean
|
||||
*/
|
||||
public function update_item_permissions_check( $request ) {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return new \WP_Error( 'woocommerce_rest_cannot_update', __( 'Sorry, you cannot manage options.', 'woocommerce-admin' ), array( 'status' => rest_authorization_required_code() ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of options and respective values.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return array Options object with option values.
|
||||
*/
|
||||
public function get_options( $request ) {
|
||||
$params = explode( ',', $request[ 'options' ] );
|
||||
$options = array();
|
||||
|
||||
if ( ! is_array( $params ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
foreach ( $params as $option ) {
|
||||
$options[ $option ] = get_option( $option );
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an array of objects.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return array Options object with a boolean if the option was updated.
|
||||
*/
|
||||
public function update_options( $request ) {
|
||||
$params = $request->get_json_params();
|
||||
$updated = array();
|
||||
|
||||
if ( ! is_array( $params ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
foreach ( $params as $key => $value ) {
|
||||
$updated[ $key ] = update_option( $key, $value );
|
||||
}
|
||||
|
||||
return $updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'options',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'options' => array(
|
||||
'type' => 'array',
|
||||
'description' => __( 'Array of options with associated values.', 'woocommerce-admin' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $this->add_additional_fields_schema( $schema );
|
||||
}
|
||||
}
|
|
@ -54,6 +54,7 @@ class Onboarding {
|
|||
}
|
||||
|
||||
// Include WC Admin Onboarding classes.
|
||||
// @todo We should return early if should_show_profiler and a new method should_show_tasks are both false.
|
||||
OnboardingTasks::get_instance();
|
||||
|
||||
add_action( 'woocommerce_components_settings', array( $this, 'component_settings' ), 20 ); // Run after Automattic\WooCommerce\Admin\Loader.
|
||||
|
|
|
@ -47,11 +47,19 @@ class OnboardingTasks {
|
|||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'add_media_scripts' ) );
|
||||
add_action( 'woocommerce_components_settings', array( $this, 'component_settings' ), 30 ); // Run after Onboarding.
|
||||
add_action( 'admin_init', array( $this, 'set_active_task' ), 20 );
|
||||
add_action( 'admin_init', array( $this, 'check_active_task_completion' ), 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue scripts and styles.
|
||||
*/
|
||||
public function add_media_scripts() {
|
||||
wp_enqueue_media();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add task items to component settings.
|
||||
*
|
||||
|
@ -72,6 +80,7 @@ class OnboardingTasks {
|
|||
}
|
||||
|
||||
$settings['onboarding']['automatedTaxSupportedCountries'] = self::get_automated_tax_supported_countries();
|
||||
$settings['onboarding']['customLogo'] = get_theme_mod( 'custom_logo', false );
|
||||
$settings['onboarding']['tasks'] = $tasks;
|
||||
$settings['onboarding']['shippingZonesCount'] = count( \WC_Shipping_Zones::get_zones() );
|
||||
|
||||
|
|
Loading…
Reference in New Issue