Options: Add data store (https://github.com/woocommerce/woocommerce-admin/pull/4144)
This commit is contained in:
parent
9be6bdd841
commit
41eeb4f9f9
|
@ -4,7 +4,7 @@
|
|||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { Fragment, Suspense, lazy, useState } from '@wordpress/element';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { partial, get } from 'lodash';
|
||||
import { partial } from 'lodash';
|
||||
import { Dropdown, Button, Icon } from '@wordpress/components';
|
||||
import { applyFilters } from '@wordpress/hooks';
|
||||
import { Icon as WPIcon, plusCircleFilled } from '@wordpress/icons';
|
||||
|
@ -15,6 +15,7 @@ import { Icon as WPIcon, plusCircleFilled } from '@wordpress/icons';
|
|||
import { H, Spinner } from '@woocommerce/components';
|
||||
import {
|
||||
SETTINGS_STORE_NAME,
|
||||
OPTIONS_STORE_NAME,
|
||||
useUserPreferences,
|
||||
} from '@woocommerce/data';
|
||||
|
||||
|
@ -329,8 +330,7 @@ const CustomizableDashboard = ( {
|
|||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getOptions } = select( 'wc-api' );
|
||||
|
||||
const { getOption } = select( OPTIONS_STORE_NAME );
|
||||
const { woocommerce_default_date_range: defaultDateRange } = select(
|
||||
SETTINGS_STORE_NAME
|
||||
).getSetting( 'wc_admin', 'wcAdminSettings' );
|
||||
|
@ -340,16 +340,13 @@ export default compose(
|
|||
};
|
||||
|
||||
if ( isOnboardingEnabled() ) {
|
||||
const options = getOptions( [
|
||||
'woocommerce_task_list_complete',
|
||||
'woocommerce_task_list_hidden',
|
||||
] );
|
||||
withSelectData.homepageEnabled =
|
||||
window.wcAdminFeatures.homepage &&
|
||||
getOption( 'woocommerce_homescreen_enabled' ) === 'yes';
|
||||
withSelectData.taskListHidden =
|
||||
get( options, [ 'woocommerce_task_list_hidden' ], 'no' ) ===
|
||||
'yes';
|
||||
getOption( 'woocommerce_task_list_hidden' ) === 'yes';
|
||||
withSelectData.taskListComplete =
|
||||
get( options, [ 'woocommerce_task_list_complete' ], 'no' ) ===
|
||||
'yes';
|
||||
getOption( 'woocommerce_task_list_complete' ) === 'yes';
|
||||
}
|
||||
|
||||
return withSelectData;
|
||||
|
|
|
@ -51,6 +51,7 @@ export function getProductIdsForCart(
|
|||
installedPlugins
|
||||
) {
|
||||
const onboarding = getSetting( 'onboarding', {} );
|
||||
const productIds = [];
|
||||
|
||||
// The population of onboarding.productTypes only happens if the task list should be shown
|
||||
// so bail early if it isn't present.
|
||||
|
@ -58,7 +59,6 @@ export function getProductIdsForCart(
|
|||
return productIds;
|
||||
}
|
||||
|
||||
const productIds = [];
|
||||
const productTypes = profileItems.product_types || [];
|
||||
|
||||
productTypes.forEach( ( productType ) => {
|
||||
|
|
|
@ -11,9 +11,13 @@ import {
|
|||
} from '@wordpress/element';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import classnames from 'classnames';
|
||||
import { get } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
|
@ -21,9 +25,9 @@ import QuickLinks from '../quick-links';
|
|||
import StatsOverview from './stats-overview';
|
||||
import './style.scss';
|
||||
import { isOnboardingEnabled } from 'dashboard/utils';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import TaskListPlaceholder from '../task-list/placeholder';
|
||||
import InboxPanel from '../header/activity-panel/panels/inbox';
|
||||
import withWCApiSelect from 'wc-api/with-select';
|
||||
|
||||
const TaskList = lazy( () =>
|
||||
import( /* webpackChunkName: "task-list" */ '../task-list' )
|
||||
|
@ -138,32 +142,27 @@ Layout.propTypes = {
|
|||
};
|
||||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
withWCApiSelect( ( select ) => {
|
||||
const {
|
||||
getOptions,
|
||||
getUndoDismissRequesting,
|
||||
isGetOptionsRequesting,
|
||||
} = select( 'wc-api' );
|
||||
const { isUndoRequesting } = getUndoDismissRequesting();
|
||||
const { getOption, isResolving } = select( OPTIONS_STORE_NAME );
|
||||
|
||||
if ( isOnboardingEnabled() ) {
|
||||
const options = getOptions( [
|
||||
'woocommerce_task_list_complete',
|
||||
'woocommerce_task_list_hidden',
|
||||
] );
|
||||
const { isUndoRequesting } = getUndoDismissRequesting();
|
||||
|
||||
return {
|
||||
isUndoRequesting,
|
||||
requestingTaskList: isGetOptionsRequesting( [
|
||||
taskListComplete:
|
||||
getOption( 'woocommerce_task_list_complete' ) === 'yes',
|
||||
taskListHidden:
|
||||
getOption( 'woocommerce_task_list_hidden' ) === 'yes',
|
||||
requestingTaskList:
|
||||
isResolving( 'getOption', [
|
||||
'woocommerce_task_list_complete',
|
||||
] ) ||
|
||||
isResolving( 'getOption', [
|
||||
'woocommerce_task_list_hidden',
|
||||
] ),
|
||||
taskListComplete:
|
||||
get( options, [ 'woocommerce_task_list_complete' ] ) ===
|
||||
'yes',
|
||||
taskListHidden:
|
||||
get( options, [ 'woocommerce_task_list_hidden' ] ) ===
|
||||
'yes',
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import { withSelect } from '@wordpress/data';
|
|||
import { Component, lazy, Suspense } from '@wordpress/element';
|
||||
import { Router, Route, Switch } from 'react-router-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { get, isFunction } from 'lodash';
|
||||
import { get, isFunction, identity } from 'lodash';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
|
@ -14,7 +14,12 @@ import { get, isFunction } from 'lodash';
|
|||
import { useFilters, Spinner } from '@woocommerce/components';
|
||||
import { getHistory } from '@woocommerce/navigation';
|
||||
import { getSetting } from '@woocommerce/wc-admin-settings';
|
||||
import { PLUGINS_STORE_NAME, withPluginsHydration } from '@woocommerce/data';
|
||||
import {
|
||||
OPTIONS_STORE_NAME,
|
||||
PLUGINS_STORE_NAME,
|
||||
withPluginsHydration,
|
||||
withOptionsHydration,
|
||||
} from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -25,7 +30,6 @@ import Header from 'header';
|
|||
import Notices from './notices';
|
||||
import { recordPageView } from 'lib/tracks';
|
||||
import TransientNotices from './transient-notices';
|
||||
import withWCApiSelect from 'wc-api/with-select';
|
||||
const StoreAlerts = lazy( () =>
|
||||
import( /* webpackChunkName: "store-alerts" */ './store-alerts' )
|
||||
);
|
||||
|
@ -211,13 +215,16 @@ class _PageLayout extends Component {
|
|||
export const PageLayout = compose(
|
||||
// Use the useFilters HoC so PageLayout is re-rendered when filters are used to add new pages or reports
|
||||
useFilters( [ PAGES_FILTER, REPORTS_FILTER ] ),
|
||||
withWCApiSelect( ( select ) => {
|
||||
const { getOptions } = select( 'wc-api' );
|
||||
const options = getOptions( [ 'woocommerce_homescreen_enabled' ] );
|
||||
window.wcSettings.preloadOptions
|
||||
? withOptionsHydration( {
|
||||
...window.wcSettings.preloadOptions,
|
||||
} )
|
||||
: identity,
|
||||
withSelect( ( select ) => {
|
||||
const { getOption } = select( OPTIONS_STORE_NAME );
|
||||
const homepageEnabled =
|
||||
window.wcAdminFeatures.homepage &&
|
||||
get( options, [ 'woocommerce_homescreen_enabled' ], false ) ===
|
||||
'yes';
|
||||
getOption( 'woocommerce_homescreen_enabled' ) === 'yes';
|
||||
return { homepageEnabled };
|
||||
} )
|
||||
)( _PageLayout );
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
*/
|
||||
import { getSetting } from '@woocommerce/wc-admin-settings';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { withOptionsHydration } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
|
@ -26,4 +31,6 @@ const MarketingOverview = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export default MarketingOverview;
|
||||
export default withOptionsHydration( {
|
||||
...( window.wcSettings.preloadOptions || {} ),
|
||||
} )( MarketingOverview );
|
||||
|
|
|
@ -2,24 +2,23 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { get } from 'lodash';
|
||||
import { Button } from '@wordpress/components';
|
||||
import Gridicon from 'gridicons';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { Card } from '@woocommerce/components';
|
||||
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
import { recordEvent } from 'lib/tracks';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import WelcomeImage from './images/welcome.svg';
|
||||
|
||||
const WelcomeCard = ( {
|
||||
|
@ -72,17 +71,17 @@ export { WelcomeCard }
|
|||
// default export
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getOptions, isUpdateOptionsRequesting } = select( 'wc-api' );
|
||||
const hideOptionName = 'woocommerce_marketing_overview_welcome_hidden';
|
||||
const options = getOptions( [ hideOptionName ] );
|
||||
const isHidden = get( options, [ hideOptionName ], 'no' ) === 'yes';
|
||||
const isUpdateRequesting = Boolean( isUpdateOptionsRequesting( [ hideOptionName ] ) );
|
||||
const { getOption, isOptionsUpdating } = select( OPTIONS_STORE_NAME );
|
||||
const isUpdateRequesting = isOptionsUpdating();
|
||||
|
||||
return {
|
||||
isHidden: isHidden || isUpdateRequesting,
|
||||
isHidden:
|
||||
getOption( 'woocommerce_marketing_overview_welcome_hidden' ) ===
|
||||
'yes' || isUpdateRequesting,
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
return {
|
||||
updateOptions,
|
||||
};
|
||||
|
|
|
@ -247,7 +247,9 @@ const hydrateSettings =
|
|||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getNotes } = select( 'wc-api' );
|
||||
const { getProfileItems, getOnboardingError } = select( ONBOARDING_STORE_NAME );
|
||||
const { getProfileItems, getOnboardingError } = select(
|
||||
ONBOARDING_STORE_NAME
|
||||
);
|
||||
const { getActivePlugins } = select( PLUGINS_STORE_NAME );
|
||||
|
||||
const notesQuery = {
|
||||
|
|
|
@ -5,7 +5,7 @@ import { __, _n, sprintf } from '@wordpress/i18n';
|
|||
import { Button } from '@wordpress/components';
|
||||
import { Component } from '@wordpress/element';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
import { filter } from 'lodash';
|
||||
|
||||
/**
|
||||
|
@ -17,6 +17,7 @@ import {
|
|||
pluginNames,
|
||||
ONBOARDING_STORE_NAME,
|
||||
PLUGINS_STORE_NAME,
|
||||
OPTIONS_STORE_NAME
|
||||
} from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
|
@ -28,7 +29,6 @@ import ManagementIcon from './images/management';
|
|||
import SalesTaxIcon from './images/sales_tax';
|
||||
import ShippingLabels from './images/shipping_labels';
|
||||
import SpeedIcon from './images/speed';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import { recordEvent } from 'lib/tracks';
|
||||
|
||||
class Benefits extends Component {
|
||||
|
@ -108,12 +108,12 @@ class Benefits extends Component {
|
|||
goToNextStep();
|
||||
}
|
||||
|
||||
async startPluginInstall() {
|
||||
startPluginInstall() {
|
||||
const { updateProfileItems, updateOptions } = this.props;
|
||||
|
||||
this.setState( { isInstalling: true } );
|
||||
|
||||
await updateOptions( {
|
||||
updateOptions( {
|
||||
woocommerce_setup_jetpack_opted_in: true,
|
||||
} );
|
||||
|
||||
|
@ -328,7 +328,7 @@ export default compose(
|
|||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { updateProfileItems } = dispatch( ONBOARDING_STORE_NAME );
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
|
||||
return {
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { Component } from '@wordpress/element';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
import { get } from 'lodash';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
import interpolateComponents from 'interpolate-components';
|
||||
import {
|
||||
Button,
|
||||
|
@ -14,11 +13,15 @@ import {
|
|||
Modal,
|
||||
} from '@wordpress/components';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { Link } from '@woocommerce/components';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
|
||||
class UsageModal extends Component {
|
||||
constructor( props ) {
|
||||
|
@ -159,20 +162,15 @@ class UsageModal extends Component {
|
|||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const {
|
||||
getOptions,
|
||||
getOptionsError,
|
||||
isUpdateOptionsRequesting,
|
||||
} = select( 'wc-api' );
|
||||
getOption,
|
||||
getOptionsUpdatingError,
|
||||
isOptionsUpdating,
|
||||
} = select( OPTIONS_STORE_NAME );
|
||||
|
||||
const options = getOptions( [ 'woocommerce_allow_tracking' ] );
|
||||
const allowTracking =
|
||||
get( options, [ 'woocommerce_allow_tracking' ], false ) === 'yes';
|
||||
const isRequesting = Boolean(
|
||||
isUpdateOptionsRequesting( [ 'woocommerce_allow_tracking' ] )
|
||||
);
|
||||
const hasErrors = Boolean(
|
||||
getOptionsError( [ 'woocommerce_allow_tracking' ] )
|
||||
);
|
||||
getOption( 'woocommerce_allow_tracking' ) === 'yes';
|
||||
const isRequesting = Boolean( isOptionsUpdating() );
|
||||
const hasErrors = Boolean( getOptionsUpdatingError() );
|
||||
|
||||
return {
|
||||
allowTracking,
|
||||
|
@ -182,7 +180,7 @@ export default compose(
|
|||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
|
||||
return {
|
||||
createNotice,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Component, cloneElement, Fragment } from '@wordpress/element';
|
||||
import { get, isEqual } from 'lodash';
|
||||
import { isEqual } from 'lodash';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
|
@ -21,7 +21,11 @@ import { Icon, check, chevronRight } from '@wordpress/icons';
|
|||
*/
|
||||
import { H, List, EllipsisMenu } from '@woocommerce/components';
|
||||
import { updateQueryString } from '@woocommerce/navigation';
|
||||
import { ONBOARDING_STORE_NAME, PLUGINS_STORE_NAME } from '@woocommerce/data';
|
||||
import {
|
||||
PLUGINS_STORE_NAME,
|
||||
OPTIONS_STORE_NAME,
|
||||
ONBOARDING_STORE_NAME,
|
||||
} from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -118,7 +122,7 @@ class TaskDashboard extends Component {
|
|||
|
||||
return getAllTasks( {
|
||||
profileItems,
|
||||
options: taskListPayments,
|
||||
taskListPayments,
|
||||
query,
|
||||
toggleCartModal: this.toggleCartModal.bind( this ),
|
||||
installedPlugins,
|
||||
|
@ -383,7 +387,7 @@ class TaskDashboard extends Component {
|
|||
export default compose(
|
||||
withSelect( ( select, props ) => {
|
||||
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
|
||||
const { getOptions } = select( 'wc-api' );
|
||||
const { getOption } = select( OPTIONS_STORE_NAME );
|
||||
const {
|
||||
getActivePlugins,
|
||||
getInstalledPlugins,
|
||||
|
@ -391,28 +395,18 @@ export default compose(
|
|||
} = select( PLUGINS_STORE_NAME );
|
||||
const profileItems = getProfileItems();
|
||||
|
||||
const options = getOptions( [
|
||||
'woocommerce_task_list_welcome_modal_dismissed',
|
||||
'woocommerce_task_list_hidden',
|
||||
'woocommerce_task_list_tracked_completed_tasks',
|
||||
] );
|
||||
const modalDismissed = get(
|
||||
options,
|
||||
[ 'woocommerce_task_list_welcome_modal_dismissed' ],
|
||||
false
|
||||
);
|
||||
const taskListPayments = getOptions( [
|
||||
'woocommerce_task_list_payments',
|
||||
] );
|
||||
const trackedCompletedTasks = get(
|
||||
options,
|
||||
[ 'woocommerce_task_list_tracked_completed_tasks' ],
|
||||
[]
|
||||
);
|
||||
const modalDismissed =
|
||||
getOption( 'woocommerce_task_list_welcome_modal_dismissed' ) ||
|
||||
false;
|
||||
const taskListPayments = getOption( 'woocommerce_task_list_payments' );
|
||||
const trackedCompletedTasks =
|
||||
getOption( 'woocommerce_task_list_tracked_completed_tasks' ) || [];
|
||||
const payments = getOption( 'woocommerce_task_list_payments' );
|
||||
|
||||
const installedPlugins = getInstalledPlugins();
|
||||
const tasks = getAllTasks( {
|
||||
profileItems,
|
||||
options: getOptions( [ 'woocommerce_task_list_payments' ] ),
|
||||
options: payments,
|
||||
query: props.query,
|
||||
installedPlugins,
|
||||
} );
|
||||
|
@ -437,7 +431,7 @@ export default compose(
|
|||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
return {
|
||||
updateOptions,
|
||||
};
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { applyFilters } from '@wordpress/hooks';
|
||||
import { get } from 'lodash';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
|
@ -25,7 +24,7 @@ import Payments from './tasks/payments';
|
|||
|
||||
export function getAllTasks( {
|
||||
profileItems,
|
||||
options,
|
||||
taskListPayments,
|
||||
query,
|
||||
toggleCartModal,
|
||||
installedPlugins,
|
||||
|
@ -55,15 +54,11 @@ export function getAllTasks( {
|
|||
installedPlugins
|
||||
);
|
||||
|
||||
const paymentsCompleted = get(
|
||||
options,
|
||||
[ 'woocommerce_task_list_payments', 'completed' ],
|
||||
false
|
||||
const paymentsCompleted = Boolean(
|
||||
taskListPayments && taskListPayments.completed
|
||||
);
|
||||
const paymentsSkipped = get(
|
||||
options,
|
||||
[ 'woocommerce_task_list_payments', 'skipped' ],
|
||||
false
|
||||
const paymentsSkipped = Boolean(
|
||||
taskListPayments && taskListPayments.skipped
|
||||
);
|
||||
|
||||
const tasks = [
|
||||
|
|
|
@ -6,8 +6,8 @@ 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';
|
||||
import { filter } from 'lodash';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
|
@ -20,13 +20,13 @@ import {
|
|||
} from '@woocommerce/components';
|
||||
import { getHistory, getNewPath } from '@woocommerce/navigation';
|
||||
import { getSetting, setSetting } from '@woocommerce/wc-admin-settings';
|
||||
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* 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 ) {
|
||||
|
@ -43,7 +43,9 @@ class Appearance extends Component {
|
|||
isPending: false,
|
||||
logo: null,
|
||||
stepIndex: 0,
|
||||
storeNoticeText: props.options.woocommerce_demo_store_notice || '',
|
||||
isUpdatingLogo: false,
|
||||
isUpdatingNotice: false,
|
||||
storeNoticeText: props.demoStoreNotice || '',
|
||||
};
|
||||
|
||||
this.completeStep = this.completeStep.bind( this );
|
||||
|
@ -63,18 +65,9 @@ class Appearance extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
componentDidUpdate( prevProps ) {
|
||||
const { isPending, logo } = this.state;
|
||||
const { demoStoreNotice } = this.props;
|
||||
|
||||
if ( logo && ! logo.url && ! isPending ) {
|
||||
/* eslint-disable react/no-did-update-set-state */
|
||||
|
@ -93,38 +86,15 @@ class Appearance extends Component {
|
|||
}
|
||||
|
||||
if (
|
||||
options.woocommerce_demo_store_notice &&
|
||||
prevProps.options.woocommerce_demo_store_notice !==
|
||||
options.woocommerce_demo_store_notice
|
||||
demoStoreNotice &&
|
||||
prevProps.demoStoreNotice !== demoStoreNotice
|
||||
) {
|
||||
/* eslint-disable react/no-did-update-set-state */
|
||||
this.setState( {
|
||||
storeNoticeText: options.woocommerce_demo_store_notice,
|
||||
storeNoticeText: demoStoreNotice,
|
||||
} );
|
||||
/* 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() {
|
||||
|
@ -222,8 +192,8 @@ class Appearance extends Component {
|
|||
} );
|
||||
}
|
||||
|
||||
updateLogo() {
|
||||
const { updateOptions } = this.props;
|
||||
async updateLogo() {
|
||||
const { updateOptions, createNotice } = this.props;
|
||||
const { logo } = this.state;
|
||||
const { stylesheet, themeMods } = getSetting( 'onboarding', {} );
|
||||
const updatedThemeMods = {
|
||||
|
@ -238,13 +208,25 @@ class Appearance extends Component {
|
|||
themeMods: updatedThemeMods,
|
||||
} );
|
||||
|
||||
updateOptions( {
|
||||
this.setState( { isUpdatingLogo: true } );
|
||||
const update = await updateOptions( {
|
||||
[ `theme_mods_${ stylesheet }` ]: updatedThemeMods,
|
||||
} );
|
||||
|
||||
if ( update.success ) {
|
||||
this.setState( { isUpdatingLogo: false } );
|
||||
createNotice(
|
||||
'success',
|
||||
__( 'Store logo updated sucessfully.', 'woocommerce-admin' )
|
||||
);
|
||||
this.completeStep();
|
||||
} else {
|
||||
createNotice( 'error', update.message );
|
||||
}
|
||||
}
|
||||
|
||||
updateNotice() {
|
||||
const { updateOptions } = this.props;
|
||||
async updateNotice() {
|
||||
const { updateOptions, createNotice } = this.props;
|
||||
const { storeNoticeText } = this.state;
|
||||
|
||||
recordEvent( 'tasklist_appearance_set_store_notice', {
|
||||
|
@ -256,16 +238,36 @@ class Appearance extends Component {
|
|||
isAppearanceComplete: true,
|
||||
} );
|
||||
|
||||
updateOptions( {
|
||||
this.setState( { isUpdatingNotice: true } );
|
||||
const update = await updateOptions( {
|
||||
woocommerce_task_list_appearance_complete: true,
|
||||
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.",
|
||||
'woocommerce-admin'
|
||||
)
|
||||
);
|
||||
this.completeStep();
|
||||
} else {
|
||||
createNotice( 'error', update.message );
|
||||
}
|
||||
}
|
||||
|
||||
getSteps() {
|
||||
const { isDirty, isPending, logo, storeNoticeText } = this.state;
|
||||
const { isRequesting } = this.props;
|
||||
const {
|
||||
isDirty,
|
||||
isPending,
|
||||
logo,
|
||||
storeNoticeText,
|
||||
isUpdatingLogo,
|
||||
} = this.state;
|
||||
|
||||
const steps = [
|
||||
{
|
||||
|
@ -340,7 +342,7 @@ class Appearance extends Component {
|
|||
<Button
|
||||
disabled={ ! logo && ! isDirty }
|
||||
onClick={ this.updateLogo }
|
||||
isBusy={ isRequesting }
|
||||
isBusy={ isUpdatingLogo }
|
||||
isPrimary
|
||||
>
|
||||
{ __( 'Proceed', 'woocommerce-admin' ) }
|
||||
|
@ -388,8 +390,12 @@ class Appearance extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { isPending, stepIndex } = this.state;
|
||||
const { isRequesting, hasErrors } = this.props;
|
||||
const {
|
||||
isPending,
|
||||
stepIndex,
|
||||
isUpdatingLogo,
|
||||
isUpdatingNotice,
|
||||
} = this.state;
|
||||
const currentStep = this.getSteps()[ stepIndex ].key;
|
||||
|
||||
return (
|
||||
|
@ -397,7 +403,7 @@ class Appearance extends Component {
|
|||
<Card className="is-narrow">
|
||||
<Stepper
|
||||
isPending={
|
||||
( isRequesting && ! hasErrors ) || isPending
|
||||
isUpdatingNotice || isUpdatingLogo || isPending
|
||||
}
|
||||
isVertical
|
||||
currentStep={ currentStep }
|
||||
|
@ -411,49 +417,15 @@ class Appearance extends Component {
|
|||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const {
|
||||
getOptions,
|
||||
getOptionsError,
|
||||
isUpdateOptionsRequesting,
|
||||
} = select( 'wc-api' );
|
||||
const { stylesheet } = getSetting( 'onboarding', {} );
|
||||
const { getOption } = select( OPTIONS_STORE_NAME );
|
||||
|
||||
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 };
|
||||
return {
|
||||
demoStoreNotice: getOption( 'woocommerce_demo_store_notice' ),
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
|
||||
return {
|
||||
createNotice,
|
||||
|
|
|
@ -5,17 +5,13 @@ import { __ } from '@wordpress/i18n';
|
|||
import { Component, Fragment } from '@wordpress/element';
|
||||
import { Button } from '@wordpress/components';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { Form, H, TextControl } from '@woocommerce/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
|
||||
class PayFast extends Component {
|
||||
getInitialConfigValues = () => {
|
||||
|
@ -42,16 +38,17 @@ class PayFast extends Component {
|
|||
return errors;
|
||||
};
|
||||
|
||||
componentDidUpdate( prevProps ) {
|
||||
const {
|
||||
createNotice,
|
||||
isOptionsRequesting,
|
||||
hasOptionsError,
|
||||
markConfigured,
|
||||
} = this.props;
|
||||
updateSettings = async ( values ) => {
|
||||
const { updateOptions, createNotice, markConfigured } = this.props;
|
||||
|
||||
if ( prevProps.isOptionsRequesting && ! isOptionsRequesting ) {
|
||||
if ( ! hasOptionsError ) {
|
||||
const update = await updateOptions( {
|
||||
woocommerce_bacs_settings: {
|
||||
enabled: 'yes',
|
||||
},
|
||||
woocommerce_bacs_accounts: [ values ],
|
||||
} );
|
||||
|
||||
if ( update.success ) {
|
||||
markConfigured( 'bacs' );
|
||||
createNotice(
|
||||
'success',
|
||||
|
@ -69,18 +66,6 @@ class PayFast extends Component {
|
|||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateSettings = ( values ) => {
|
||||
const { updateOptions } = this.props;
|
||||
|
||||
updateOptions( {
|
||||
woocommerce_bacs_settings: {
|
||||
enabled: 'yes',
|
||||
},
|
||||
woocommerce_bacs_accounts: [ values ],
|
||||
} );
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -171,28 +156,16 @@ class PayFast extends Component {
|
|||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getOptionsError, isUpdateOptionsRequesting } = select(
|
||||
'wc-api'
|
||||
);
|
||||
const isOptionsRequesting = Boolean(
|
||||
isUpdateOptionsRequesting( [
|
||||
'woocommerce_bacs_settings',
|
||||
'woocommerce_bacs_accounts',
|
||||
] )
|
||||
);
|
||||
const hasOptionsError = getOptionsError( [
|
||||
'woocommerce_bacs_settings',
|
||||
'woocommerce_bacs_accounts',
|
||||
] );
|
||||
const { isOptionsUpdating } = select( OPTIONS_STORE_NAME );
|
||||
const isOptionsRequesting = isOptionsUpdating();
|
||||
|
||||
return {
|
||||
hasOptionsError,
|
||||
isOptionsRequesting,
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
|
||||
return {
|
||||
createNotice,
|
||||
|
|
|
@ -19,8 +19,9 @@ import {
|
|||
} from '@woocommerce/navigation';
|
||||
import {
|
||||
ONBOARDING_STORE_NAME,
|
||||
pluginNames,
|
||||
OPTIONS_STORE_NAME,
|
||||
PLUGINS_STORE_NAME,
|
||||
pluginNames,
|
||||
} from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
|
@ -53,32 +54,15 @@ class Payments extends Component {
|
|||
if ( prevProps === this.props ) {
|
||||
return;
|
||||
}
|
||||
const { createNotice, errors, methods, requesting } = this.props;
|
||||
const { methods } = this.props;
|
||||
|
||||
let recommendedMethod = 'stripe';
|
||||
methods.forEach( ( method ) => {
|
||||
const { key, title, visible } = method;
|
||||
const { key, visible } = method;
|
||||
|
||||
if ( key === 'wcpay' && visible ) {
|
||||
recommendedMethod = 'wcpay';
|
||||
}
|
||||
|
||||
if (
|
||||
prevProps.requesting[ key ] &&
|
||||
! requesting[ key ] &&
|
||||
errors[ key ]
|
||||
) {
|
||||
createNotice(
|
||||
'error',
|
||||
sprintf(
|
||||
__(
|
||||
'There was a problem updating settings for %s',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
title
|
||||
)
|
||||
);
|
||||
}
|
||||
} );
|
||||
|
||||
if ( this.state.recommendedMethod !== recommendedMethod ) {
|
||||
|
@ -88,10 +72,10 @@ class Payments extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
completeTask() {
|
||||
async completeTask() {
|
||||
const { createNotice, methods, updateOptions } = this.props;
|
||||
|
||||
updateOptions( {
|
||||
const update = await updateOptions( {
|
||||
woocommerce_task_list_payments: {
|
||||
completed: 1,
|
||||
timestamp: Math.floor( Date.now() / 1000 ),
|
||||
|
@ -104,6 +88,7 @@ class Payments extends Component {
|
|||
.map( ( method ) => method.key ),
|
||||
} );
|
||||
|
||||
if ( update.success ) {
|
||||
createNotice(
|
||||
'success',
|
||||
__(
|
||||
|
@ -113,6 +98,15 @@ class Payments extends Component {
|
|||
);
|
||||
|
||||
getHistory().push( getNewPath( {}, '/', {} ) );
|
||||
} else {
|
||||
createNotice(
|
||||
'error',
|
||||
__(
|
||||
'There was a problem updating settings',
|
||||
'woocommerce-admin'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
skipTask() {
|
||||
|
@ -218,8 +212,8 @@ class Payments extends Component {
|
|||
|
||||
render() {
|
||||
const currentMethod = this.getCurrentMethod();
|
||||
const { methods, query } = this.props;
|
||||
const { enabledMethods, recommendedMethod } = this.state;
|
||||
const { methods, query, requesting } = this.props;
|
||||
const configuredMethods = methods.filter(
|
||||
( method ) => method.isConfigured
|
||||
).length;
|
||||
|
@ -344,7 +338,11 @@ class Payments extends Component {
|
|||
) }
|
||||
</Button>
|
||||
) : (
|
||||
<Button isPrimary onClick={ this.completeTask }>
|
||||
<Button
|
||||
isPrimary
|
||||
isBusy={ requesting }
|
||||
onClick={ this.completeTask }
|
||||
>
|
||||
{ __( 'Done', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
) }
|
||||
|
@ -357,18 +355,15 @@ class Payments extends Component {
|
|||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
|
||||
const {
|
||||
getOptions,
|
||||
getUpdateOptionsError,
|
||||
isUpdateOptionsRequesting,
|
||||
} = select( 'wc-api' );
|
||||
|
||||
const { getOption, isOptionsUpdating } = select( OPTIONS_STORE_NAME );
|
||||
const { getActivePlugins, isJetpackConnected } = select(
|
||||
PLUGINS_STORE_NAME
|
||||
);
|
||||
|
||||
const activePlugins = getActivePlugins();
|
||||
const profileItems = getProfileItems();
|
||||
const options = getOptions( [
|
||||
|
||||
const optionNames = [
|
||||
'woocommerce_default_country',
|
||||
'woocommerce_woocommerce_payments_settings',
|
||||
'woocommerce_stripe_settings',
|
||||
|
@ -381,7 +376,12 @@ export default compose(
|
|||
'woocommerce_cod_settings',
|
||||
'woocommerce_bacs_settings',
|
||||
'woocommerce_bacs_accounts',
|
||||
] );
|
||||
];
|
||||
|
||||
const options = optionNames.reduce( ( result, name ) => {
|
||||
result[ name ] = getOption( name );
|
||||
return result;
|
||||
}, {} );
|
||||
const countryCode = getCountryCode(
|
||||
options.woocommerce_default_country
|
||||
);
|
||||
|
@ -394,20 +394,10 @@ export default compose(
|
|||
profileItems,
|
||||
} );
|
||||
|
||||
const errors = {};
|
||||
const requesting = {};
|
||||
methods.forEach( ( method ) => {
|
||||
errors[ method.key ] = Boolean(
|
||||
getUpdateOptionsError( [ method.optionName ] )
|
||||
);
|
||||
requesting[ method.key ] = Boolean(
|
||||
isUpdateOptionsRequesting( [ method.optionName ] )
|
||||
);
|
||||
} );
|
||||
const requesting = isOptionsUpdating();
|
||||
|
||||
return {
|
||||
countryCode,
|
||||
errors,
|
||||
profileItems,
|
||||
activePlugins,
|
||||
options,
|
||||
|
@ -417,7 +407,7 @@ export default compose(
|
|||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
return {
|
||||
createNotice,
|
||||
updateOptions,
|
||||
|
|
|
@ -6,17 +6,13 @@ import { Component, Fragment } from '@wordpress/element';
|
|||
import { Button } from '@wordpress/components';
|
||||
import interpolateComponents from 'interpolate-components';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { Form, Link, Stepper, TextControl } from '@woocommerce/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
|
||||
class PayFast extends Component {
|
||||
getInitialConfigValues = () => {
|
||||
|
@ -54,16 +50,22 @@ class PayFast extends Component {
|
|||
return errors;
|
||||
};
|
||||
|
||||
componentDidUpdate( prevProps ) {
|
||||
const {
|
||||
createNotice,
|
||||
isOptionsRequesting,
|
||||
hasOptionsError,
|
||||
markConfigured,
|
||||
} = this.props;
|
||||
updateSettings = async ( values ) => {
|
||||
const { updateOptions, createNotice, markConfigured } = this.props;
|
||||
|
||||
if ( prevProps.isOptionsRequesting && ! isOptionsRequesting ) {
|
||||
if ( ! hasOptionsError ) {
|
||||
// Because the PayFast extension only works with the South African Rand
|
||||
// currency, force the store to use it while setting the PayFast settings
|
||||
const update = await updateOptions( {
|
||||
woocommerce_currency: 'ZAR',
|
||||
woocommerce_payfast_settings: {
|
||||
merchant_id: values.merchant_id,
|
||||
merchant_key: values.merchant_key,
|
||||
pass_phrase: values.pass_phrase,
|
||||
enabled: 'yes',
|
||||
},
|
||||
} );
|
||||
|
||||
if ( update.success ) {
|
||||
markConfigured( 'payfast' );
|
||||
createNotice(
|
||||
'success',
|
||||
|
@ -78,23 +80,6 @@ class PayFast extends Component {
|
|||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateSettings = ( values ) => {
|
||||
const { updateOptions } = this.props;
|
||||
|
||||
// Because the PayFast extension only works with the South African Rand
|
||||
// currency, force the store to use it while setting the PayFast settings
|
||||
updateOptions( {
|
||||
woocommerce_currency: 'ZAR',
|
||||
woocommerce_payfast_settings: {
|
||||
merchant_id: values.merchant_id,
|
||||
merchant_key: values.merchant_key,
|
||||
pass_phrase: values.pass_phrase,
|
||||
enabled: 'yes',
|
||||
},
|
||||
} );
|
||||
};
|
||||
|
||||
renderConnectStep() {
|
||||
|
@ -190,28 +175,16 @@ class PayFast extends Component {
|
|||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getOptionsError, isUpdateOptionsRequesting } = select(
|
||||
'wc-api'
|
||||
);
|
||||
const isOptionsRequesting = Boolean(
|
||||
isUpdateOptionsRequesting( [
|
||||
'woocommerce_currency',
|
||||
'woocommerce_payfast_settings',
|
||||
] )
|
||||
);
|
||||
const hasOptionsError = getOptionsError( [
|
||||
'woocommerce_currency',
|
||||
'woocommerce_payfast_settings',
|
||||
] );
|
||||
const { isOptionsUpdating } = select( OPTIONS_STORE_NAME );
|
||||
const isOptionsRequesting = isOptionsUpdating();
|
||||
|
||||
return {
|
||||
hasOptionsError,
|
||||
isOptionsRequesting,
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
|
||||
return {
|
||||
createNotice,
|
||||
|
|
|
@ -7,7 +7,7 @@ import { Button } from '@wordpress/components';
|
|||
import { Component, Fragment } from '@wordpress/element';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import interpolateComponents from 'interpolate-components';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
|
@ -15,8 +15,7 @@ import { withDispatch } from '@wordpress/data';
|
|||
import { Form, Link, Stepper, TextControl } from '@woocommerce/components';
|
||||
import { getQuery } from '@woocommerce/navigation';
|
||||
import { WC_ADMIN_NAMESPACE } from 'wc-api/constants';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import { PLUGINS_STORE_NAME } from '@woocommerce/data';
|
||||
import { PLUGINS_STORE_NAME, OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
|
||||
class PayPal extends Component {
|
||||
constructor( props ) {
|
||||
|
@ -119,13 +118,12 @@ class PayPal extends Component {
|
|||
async updateSettings( values ) {
|
||||
const {
|
||||
createNotice,
|
||||
isSettingsError,
|
||||
options,
|
||||
updateOptions,
|
||||
markConfigured,
|
||||
} = this.props;
|
||||
|
||||
await updateOptions( {
|
||||
const update = await updateOptions( {
|
||||
woocommerce_ppec_paypal_settings: {
|
||||
...options.woocommerce_ppec_paypal_settings,
|
||||
api_username: values.api_username,
|
||||
|
@ -134,7 +132,7 @@ class PayPal extends Component {
|
|||
},
|
||||
} );
|
||||
|
||||
if ( ! isSettingsError ) {
|
||||
if ( update.success ) {
|
||||
createNotice(
|
||||
'success',
|
||||
__( 'PayPal connected successfully.', 'woocommerce-admin' )
|
||||
|
@ -178,7 +176,7 @@ class PayPal extends Component {
|
|||
}
|
||||
|
||||
renderManualConfig() {
|
||||
const { isOptionsRequesting } = this.props;
|
||||
const { isOptionsUpdating } = this.props;
|
||||
const link = (
|
||||
<Link
|
||||
href="https://docs.woocommerce.com/document/paypal-express-checkout/#section-8"
|
||||
|
@ -225,7 +223,7 @@ class PayPal extends Component {
|
|||
<Button
|
||||
onClick={ handleSubmit }
|
||||
isPrimary
|
||||
disabled={ isOptionsRequesting }
|
||||
isBusy={ isOptionsUpdating }
|
||||
>
|
||||
{ __( 'Proceed', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
|
@ -291,23 +289,20 @@ PayPal.defaultProps = {
|
|||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getOptions, isGetOptionsRequesting } = select( 'wc-api' );
|
||||
const { getOption, isOptionsUpdating } = select( OPTIONS_STORE_NAME );
|
||||
const { getActivePlugins } = select( PLUGINS_STORE_NAME );
|
||||
const options = getOptions( [ 'woocommerce_ppec_paypal_settings' ] );
|
||||
const isOptionsRequesting = Boolean(
|
||||
isGetOptionsRequesting( [ 'woocommerce_ppec_paypal_settings' ] )
|
||||
);
|
||||
const options = getOption( 'woocommerce_ppec_paypal_settings' );
|
||||
const activePlugins = getActivePlugins();
|
||||
|
||||
return {
|
||||
activePlugins,
|
||||
options,
|
||||
isOptionsRequesting,
|
||||
isOptionsUpdating: isOptionsUpdating(),
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
return {
|
||||
createNotice,
|
||||
updateOptions,
|
||||
|
|
|
@ -5,7 +5,7 @@ import { __ } from '@wordpress/i18n';
|
|||
import { Component, Fragment } from '@wordpress/element';
|
||||
import apiFetch from '@wordpress/api-fetch';
|
||||
import { Button } from '@wordpress/components';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
import { compose } from '@wordpress/compose';
|
||||
|
||||
/**
|
||||
|
@ -13,9 +13,9 @@ import { compose } from '@wordpress/compose';
|
|||
*/
|
||||
import { getQuery } from '@woocommerce/navigation';
|
||||
import { WC_ADMIN_NAMESPACE } from 'wc-api/constants';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import { Stepper } from '@woocommerce/components';
|
||||
import { getAdminLink } from '@woocommerce/wc-admin-settings';
|
||||
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
|
||||
class Square extends Component {
|
||||
constructor( props ) {
|
||||
|
@ -145,15 +145,11 @@ class Square extends Component {
|
|||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getOptions, isGetOptionsRequesting } = select( 'wc-api' );
|
||||
const options = getOptions( [
|
||||
const { getOption, isResolving } = select( OPTIONS_STORE_NAME );
|
||||
const options = getOption( 'woocommerce_square_credit_card_settings' );
|
||||
const optionsIsRequesting = isResolving( 'getOption', [
|
||||
'woocommerce_square_credit_card_settings',
|
||||
] );
|
||||
const optionsIsRequesting = Boolean(
|
||||
isGetOptionsRequesting( [
|
||||
'woocommerce_square_credit_card_settings',
|
||||
] )
|
||||
);
|
||||
|
||||
return {
|
||||
options,
|
||||
|
@ -162,7 +158,7 @@ export default compose(
|
|||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
return {
|
||||
createNotice,
|
||||
updateOptions,
|
||||
|
|
|
@ -5,10 +5,9 @@ import { __ } from '@wordpress/i18n';
|
|||
import { Component, Fragment } from '@wordpress/element';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import apiFetch from '@wordpress/api-fetch';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
import interpolateComponents from 'interpolate-components';
|
||||
import { Button } from '@wordpress/components';
|
||||
import { get } from 'lodash';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
|
@ -17,8 +16,7 @@ import { Form, Link, Stepper, TextControl } from '@woocommerce/components';
|
|||
import { getAdminLink } from '@woocommerce/wc-admin-settings';
|
||||
import { getQuery } from '@woocommerce/navigation';
|
||||
import { WCS_NAMESPACE } from 'wc-api/constants';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import { PLUGINS_STORE_NAME } from '@woocommerce/data';
|
||||
import { PLUGINS_STORE_NAME, OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
|
||||
class Stripe extends Component {
|
||||
constructor( props ) {
|
||||
|
@ -54,26 +52,7 @@ class Stripe extends Component {
|
|||
}
|
||||
|
||||
componentDidUpdate( prevProps ) {
|
||||
const {
|
||||
activePlugins,
|
||||
createNotice,
|
||||
isOptionsRequesting,
|
||||
hasOptionsError,
|
||||
} = this.props;
|
||||
|
||||
if ( prevProps.isOptionsRequesting && ! isOptionsRequesting ) {
|
||||
if ( ! hasOptionsError ) {
|
||||
this.completeMethod();
|
||||
} else {
|
||||
createNotice(
|
||||
'error',
|
||||
__(
|
||||
'There was a problem saving your payment setings',
|
||||
'woocommerce-admin'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
const { activePlugins } = this.props;
|
||||
|
||||
if (
|
||||
! prevProps.activePlugins.includes(
|
||||
|
@ -154,10 +133,10 @@ class Stripe extends Component {
|
|||
);
|
||||
}
|
||||
|
||||
updateSettings( values ) {
|
||||
const { updateOptions, stripeSettings } = this.props;
|
||||
async updateSettings( values ) {
|
||||
const { updateOptions, stripeSettings, createNotice } = this.props;
|
||||
|
||||
updateOptions( {
|
||||
const update = await updateOptions( {
|
||||
woocommerce_stripe_settings: {
|
||||
...stripeSettings,
|
||||
publishable_key: values.publishable_key,
|
||||
|
@ -165,6 +144,18 @@ class Stripe extends Component {
|
|||
enabled: 'yes',
|
||||
},
|
||||
} );
|
||||
|
||||
if ( update.success ) {
|
||||
this.completeMethod();
|
||||
} else {
|
||||
createNotice(
|
||||
'error',
|
||||
__(
|
||||
'There was a problem saving your payment setings',
|
||||
'woocommerce-admin'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getInitialConfigValues() {
|
||||
|
@ -194,7 +185,7 @@ class Stripe extends Component {
|
|||
}
|
||||
|
||||
renderManualConfig() {
|
||||
const { isOptionsRequesting } = this.props;
|
||||
const { isOptionsUpdating } = this.props;
|
||||
const stripeHelp = interpolateComponents( {
|
||||
mixedString: __(
|
||||
'Your API details can be obtained from your {{docsLink}}Stripe account{{/docsLink}}. Don’t have a Stripe account? {{registerLink}}Create one.{{/registerLink}}',
|
||||
|
@ -246,7 +237,7 @@ class Stripe extends Component {
|
|||
|
||||
<Button
|
||||
isPrimary
|
||||
isBusy={ isOptionsRequesting }
|
||||
isBusy={ isOptionsUpdating }
|
||||
onClick={ handleSubmit }
|
||||
>
|
||||
{ __( 'Proceed', 'woocommerce-admin' ) }
|
||||
|
@ -294,14 +285,14 @@ class Stripe extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { installStep, isOptionsRequesting } = this.props;
|
||||
const { installStep, isOptionsUpdating } = this.props;
|
||||
const { isPending } = this.state;
|
||||
|
||||
return (
|
||||
<Stepper
|
||||
isVertical
|
||||
isPending={
|
||||
! installStep.isComplete || isOptionsRequesting || isPending
|
||||
! installStep.isComplete || isOptionsUpdating || isPending
|
||||
}
|
||||
currentStep={ installStep.isComplete ? 'connect' : 'install' }
|
||||
steps={ [ installStep, this.getConnectStep() ] }
|
||||
|
@ -312,38 +303,21 @@ class Stripe extends Component {
|
|||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const {
|
||||
getOptions,
|
||||
getOptionsError,
|
||||
isUpdateOptionsRequesting,
|
||||
} = select( 'wc-api' );
|
||||
const { getOption, isOptionsUpdating } = select( OPTIONS_STORE_NAME );
|
||||
const { getActivePlugins, isJetpackConnected } = select(
|
||||
PLUGINS_STORE_NAME
|
||||
);
|
||||
const options = getOptions( [ 'woocommerce_stripe_settings' ] );
|
||||
const stripeSettings = get(
|
||||
options,
|
||||
[ 'woocommerce_stripe_settings' ],
|
||||
[]
|
||||
);
|
||||
const isOptionsRequesting = Boolean(
|
||||
isUpdateOptionsRequesting( [ 'woocommerce_stripe_settings' ] )
|
||||
);
|
||||
const hasOptionsError = getOptionsError( [
|
||||
'woocommerce_stripe_settings',
|
||||
] );
|
||||
|
||||
return {
|
||||
activePlugins: getActivePlugins(),
|
||||
hasOptionsError,
|
||||
isJetpackConnected: isJetpackConnected(),
|
||||
isOptionsRequesting,
|
||||
stripeSettings,
|
||||
isOptionsUpdating: isOptionsUpdating(),
|
||||
stripeSettings: getOption( 'woocommerce_stripe_settings' ) || [],
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
return {
|
||||
createNotice,
|
||||
updateOptions,
|
||||
|
|
|
@ -5,7 +5,7 @@ import { __ } from '@wordpress/i18n';
|
|||
import { Button } from '@wordpress/components';
|
||||
import { Component, Fragment } from '@wordpress/element';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { difference, filter, get } from 'lodash';
|
||||
import { difference, filter } from 'lodash';
|
||||
import interpolateComponents from 'interpolate-components';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
|
||||
|
@ -19,7 +19,11 @@ import {
|
|||
getSetting,
|
||||
setSetting,
|
||||
} from '@woocommerce/wc-admin-settings';
|
||||
import { SETTINGS_STORE_NAME, PLUGINS_STORE_NAME } from '@woocommerce/data';
|
||||
import {
|
||||
SETTINGS_STORE_NAME,
|
||||
PLUGINS_STORE_NAME,
|
||||
OPTIONS_STORE_NAME,
|
||||
} from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -27,7 +31,6 @@ import { SETTINGS_STORE_NAME, PLUGINS_STORE_NAME } from '@woocommerce/data';
|
|||
import Connect from 'dashboard/components/connect';
|
||||
import { getCountryCode } from 'dashboard/utils';
|
||||
import StoreLocation from './steps/location';
|
||||
import withWCApiSelect from 'wc-api/with-select';
|
||||
import { recordEvent, queueRecordEvent } from 'lib/tracks';
|
||||
|
||||
class Tax extends Component {
|
||||
|
@ -491,38 +494,16 @@ class Tax extends Component {
|
|||
}
|
||||
|
||||
export default compose(
|
||||
withWCApiSelect( ( select ) => {
|
||||
const { getOptions } = select( 'wc-api' );
|
||||
|
||||
const { getActivePlugins, isJetpackConnected } = select(
|
||||
PLUGINS_STORE_NAME
|
||||
);
|
||||
const activePlugins = getActivePlugins();
|
||||
const pluginsToActivate = difference(
|
||||
[ 'jetpack', 'woocommerce-services' ],
|
||||
activePlugins
|
||||
);
|
||||
const options = getOptions( [
|
||||
'wc_connect_options',
|
||||
'woocommerce_setup_jetpack_opted_in',
|
||||
] );
|
||||
const connectOptions = get( options, 'wc_connect_options', {} );
|
||||
const tosAccepted =
|
||||
connectOptions.tos_accepted ||
|
||||
options.woocommerce_setup_jetpack_opted_in;
|
||||
|
||||
return {
|
||||
isJetpackConnected: isJetpackConnected(),
|
||||
pluginsToActivate,
|
||||
tosAccepted,
|
||||
};
|
||||
} ),
|
||||
withSelect( ( select ) => {
|
||||
const {
|
||||
getSettings,
|
||||
getSettingsError,
|
||||
isGetSettingsRequesting,
|
||||
} = select( SETTINGS_STORE_NAME );
|
||||
const { getOption } = select( OPTIONS_STORE_NAME );
|
||||
const { getActivePlugins, isJetpackConnected } = select(
|
||||
PLUGINS_STORE_NAME
|
||||
);
|
||||
|
||||
const { general: generalSettings = {} } = getSettings( 'general' );
|
||||
const isGeneralSettingsError = Boolean( getSettingsError( 'general' ) );
|
||||
|
@ -537,6 +518,16 @@ export default compose(
|
|||
const isTaxSettingsError = Boolean( getSettingsError( 'tax' ) );
|
||||
const isTaxSettingsRequesting = isGetSettingsRequesting( 'tax' );
|
||||
|
||||
const activePlugins = getActivePlugins();
|
||||
const pluginsToActivate = difference(
|
||||
[ 'jetpack', 'woocommerce-services' ],
|
||||
activePlugins
|
||||
);
|
||||
const connectOptions = getOption( 'wc_connect_options' ) || {};
|
||||
const tosAccepted =
|
||||
connectOptions.tos_accepted ||
|
||||
getOption( 'woocommerce_setup_jetpack_opted_in' );
|
||||
|
||||
return {
|
||||
isGeneralSettingsError,
|
||||
isGeneralSettingsRequesting,
|
||||
|
@ -545,6 +536,9 @@ export default compose(
|
|||
taxSettings,
|
||||
isTaxSettingsError,
|
||||
isTaxSettingsRequesting,
|
||||
isJetpackConnected: isJetpackConnected(),
|
||||
pluginsToActivate,
|
||||
tosAccepted,
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import operations from './operations';
|
||||
import selectors from './selectors';
|
||||
import mutations from './mutations';
|
||||
|
||||
export default {
|
||||
operations,
|
||||
selectors,
|
||||
mutations,
|
||||
};
|
|
@ -1,16 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getResourceName } from '../utils';
|
||||
|
||||
const updateOptions = ( operations ) => ( options ) => {
|
||||
const resourceName = getResourceName(
|
||||
'options-update',
|
||||
Object.keys( options )
|
||||
);
|
||||
operations.update( [ resourceName ], { [ resourceName ]: options } );
|
||||
};
|
||||
|
||||
export default {
|
||||
updateOptions,
|
||||
};
|
|
@ -1,84 +0,0 @@
|
|||
/**
|
||||
* 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-update' );
|
||||
} );
|
||||
|
||||
return filteredNames.map( async ( resourceName ) => {
|
||||
return fetch( {
|
||||
path: url,
|
||||
method: 'POST',
|
||||
data: data[ resourceName ],
|
||||
} )
|
||||
.then( () => optionsToResource( data[ resourceName ], true ) )
|
||||
.catch( ( error ) => {
|
||||
return { [ resourceName ]: { data: {}, error } };
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
function optionsToResource( options, updateResource = false ) {
|
||||
const optionNames = Object.keys( options );
|
||||
const resourceName = getResourceName(
|
||||
updateResource ? 'options-update' : 'options',
|
||||
optionNames
|
||||
);
|
||||
const resources = {};
|
||||
|
||||
optionNames.forEach(
|
||||
( optionName ) =>
|
||||
( resources[ getResourceName( 'options', optionName ) ] = {
|
||||
data: options[ optionName ],
|
||||
} )
|
||||
);
|
||||
|
||||
return {
|
||||
[ resourceName ]: {
|
||||
data: optionNames,
|
||||
},
|
||||
...resources,
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
read,
|
||||
update,
|
||||
};
|
|
@ -1,81 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { isNil } from 'lodash';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { getSetting } from '@woocommerce/wc-admin-settings';
|
||||
|
||||
/**
|
||||
* 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 || optionNames;
|
||||
|
||||
names.forEach( ( name ) => {
|
||||
const data = getSetting(
|
||||
'preloadOptions',
|
||||
{},
|
||||
( po ) =>
|
||||
getResource( getResourceName( 'options', name ) ).data ||
|
||||
po[ name ]
|
||||
);
|
||||
if ( data ) {
|
||||
options[ name ] = data;
|
||||
}
|
||||
} );
|
||||
return options;
|
||||
};
|
||||
|
||||
const getOptionsError = ( getResource ) => ( optionNames ) => {
|
||||
return getResource( getResourceName( 'options', optionNames ) ).error;
|
||||
};
|
||||
|
||||
const getUpdateOptionsError = ( getResource ) => ( optionNames ) => {
|
||||
return getResource( getResourceName( 'options-update', optionNames ) )
|
||||
.error;
|
||||
};
|
||||
|
||||
const isGetOptionsRequesting = ( getResource ) => ( optionNames ) => {
|
||||
const { lastReceived, lastRequested } = getResource(
|
||||
getResourceName( 'options', optionNames )
|
||||
);
|
||||
|
||||
if ( isNil( lastRequested ) || isNil( lastReceived ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return lastRequested > lastReceived;
|
||||
};
|
||||
|
||||
const isUpdateOptionsRequesting = ( getResource ) => ( optionNames ) => {
|
||||
const { lastReceived, lastRequested } = getResource(
|
||||
getResourceName( 'options-update', optionNames )
|
||||
);
|
||||
|
||||
if ( ! isNil( lastRequested ) && isNil( lastReceived ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return lastRequested > lastReceived;
|
||||
};
|
||||
|
||||
export default {
|
||||
getOptions,
|
||||
getOptionsError,
|
||||
getUpdateOptionsError,
|
||||
isGetOptionsRequesting,
|
||||
isUpdateOptionsRequesting,
|
||||
};
|
|
@ -5,7 +5,6 @@ import reportExport from './export';
|
|||
import items from './items';
|
||||
import imports from './imports';
|
||||
import notes from './notes';
|
||||
import options from './options';
|
||||
import reportItems from './reports/items';
|
||||
import reportStats from './reports/stats';
|
||||
import reviews from './reviews';
|
||||
|
@ -17,13 +16,11 @@ function createWcApiSpec() {
|
|||
...reportExport.mutations,
|
||||
...items.mutations,
|
||||
...notes.mutations,
|
||||
...options.mutations,
|
||||
},
|
||||
selectors: {
|
||||
...imports.selectors,
|
||||
...items.selectors,
|
||||
...notes.selectors,
|
||||
...options.selectors,
|
||||
...reportItems.selectors,
|
||||
...reportStats.selectors,
|
||||
...reviews.selectors,
|
||||
|
@ -39,7 +36,6 @@ function createWcApiSpec() {
|
|||
...imports.operations.read( resourceNames ),
|
||||
...items.operations.read( resourceNames ),
|
||||
...notes.operations.read( resourceNames ),
|
||||
...options.operations.read( resourceNames ),
|
||||
...reportItems.operations.read( resourceNames ),
|
||||
...reportStats.operations.read( resourceNames ),
|
||||
...reviews.operations.read( resourceNames ),
|
||||
|
@ -50,7 +46,6 @@ function createWcApiSpec() {
|
|||
...reportExport.operations.update( resourceNames, data ),
|
||||
...items.operations.update( resourceNames, data ),
|
||||
...notes.operations.update( resourceNames, data ),
|
||||
...options.operations.update( resourceNames, data ),
|
||||
];
|
||||
},
|
||||
remove( resourceNames, data ) {
|
||||
|
|
|
@ -7,6 +7,11 @@ import { Button, Modal } from '@wordpress/components';
|
|||
import { withDispatch } from '@wordpress/data';
|
||||
import { compose } from '@wordpress/compose';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { OPTIONS_STORE_NAME } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
|
@ -75,7 +80,7 @@ export class DismissModal extends Component {
|
|||
|
||||
export default compose(
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
return { updateOptions };
|
||||
} )
|
||||
)( DismissModal );
|
||||
|
|
|
@ -12,3 +12,6 @@ export { withOnboardingHydration } from './onboarding/with-onboarding-hydration'
|
|||
export { USER_STORE_NAME } from './user-preferences';
|
||||
export { withCurrentUserHydration } from './user-preferences/with-current-user-hydration';
|
||||
export { useUserPreferences } from './user-preferences/use-user-preferences';
|
||||
|
||||
export { OPTIONS_STORE_NAME } from './options';
|
||||
export { withOptionsHydration } from './options/with-options-hydration';
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
const TYPES = {
|
||||
RECEIVE_OPTIONS: 'RECEIVE_OPTIONS',
|
||||
SET_IS_REQUESTING: 'SET_IS_REQUESTING',
|
||||
SET_IS_UPDATING: 'SET_IS_UPDATING',
|
||||
SET_REQUESTING_ERROR: 'SET_REQUESTING_ERROR',
|
||||
SET_UPDATING_ERROR: 'SET_UPDATING_ERROR',
|
||||
};
|
||||
|
||||
export default TYPES;
|
|
@ -0,0 +1,59 @@
|
|||
/**
|
||||
* External Dependencies
|
||||
*/
|
||||
|
||||
import { apiFetch } from '@wordpress/data-controls';
|
||||
|
||||
/**
|
||||
* Internal Dependencies
|
||||
*/
|
||||
import TYPES from './action-types';
|
||||
import { WC_ADMIN_NAMESPACE } from '../constants';
|
||||
|
||||
export function receiveOptions( options ) {
|
||||
return {
|
||||
type: TYPES.RECEIVE_OPTIONS,
|
||||
options,
|
||||
};
|
||||
}
|
||||
|
||||
export function setRequestingError( error, name ) {
|
||||
return {
|
||||
type: TYPES.SET_REQUESTING_ERROR,
|
||||
error,
|
||||
name,
|
||||
};
|
||||
}
|
||||
|
||||
export function setUpdatingError( error ) {
|
||||
return {
|
||||
type: TYPES.SET_UPDATING_ERROR,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export function setIsUpdating( isUpdating ) {
|
||||
return {
|
||||
type: TYPES.SET_IS_UPDATING,
|
||||
isUpdating,
|
||||
};
|
||||
}
|
||||
|
||||
export function* updateOptions( data ) {
|
||||
yield setIsUpdating( true );
|
||||
yield receiveOptions( data );
|
||||
|
||||
try {
|
||||
const results = yield apiFetch( {
|
||||
path: WC_ADMIN_NAMESPACE + '/options',
|
||||
method: 'POST',
|
||||
data,
|
||||
} );
|
||||
|
||||
yield setIsUpdating( false );
|
||||
return { success: true, ...results };
|
||||
} catch ( error ) {
|
||||
yield setUpdatingError( error );
|
||||
return { success: false, ...error };
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
|
||||
export const STORE_NAME = 'wc/admin/options';
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { controls as dataControls } from '@wordpress/data-controls';
|
||||
import apiFetch from '@wordpress/api-fetch';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { WC_ADMIN_NAMESPACE } from '../constants';
|
||||
|
||||
let optionNames = [];
|
||||
const fetches = {};
|
||||
|
||||
export const batchFetch = ( optionName ) => {
|
||||
return {
|
||||
type: 'BATCH_FETCH',
|
||||
optionName,
|
||||
};
|
||||
};
|
||||
|
||||
export const controls = {
|
||||
...dataControls,
|
||||
BATCH_FETCH( { optionName } ) {
|
||||
optionNames.push( optionName );
|
||||
|
||||
return new Promise( resolve => {
|
||||
setTimeout( function() {
|
||||
const names = optionNames.join(',');
|
||||
if ( fetches[ names ] ) {
|
||||
return fetches[ names ].then( ( result ) => {
|
||||
resolve( result[ optionName ] );
|
||||
} );
|
||||
}
|
||||
|
||||
const url = WC_ADMIN_NAMESPACE + '/options?options=' + names;
|
||||
fetches[ names ] = apiFetch( { path: url } );
|
||||
fetches[names].then( ( result ) => resolve( result ) )
|
||||
|
||||
// Clear option names after all resolved;
|
||||
setTimeout( () => {
|
||||
optionNames = [];
|
||||
// Delete the fetch after to allow wp data to handle cache invalidation.
|
||||
delete fetches[ names ];
|
||||
}, 1 )
|
||||
|
||||
}, 1 );
|
||||
} );
|
||||
},
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
|
||||
import { registerStore } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { STORE_NAME } from './constants';
|
||||
import * as selectors from './selectors';
|
||||
import * as actions from './actions';
|
||||
import * as resolvers from './resolvers';
|
||||
import { controls } from './controls';
|
||||
import reducer from './reducer';
|
||||
|
||||
registerStore( STORE_NAME, {
|
||||
reducer,
|
||||
actions,
|
||||
controls,
|
||||
selectors,
|
||||
resolvers,
|
||||
} );
|
||||
|
||||
export const OPTIONS_STORE_NAME = STORE_NAME;
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import TYPES from './action-types';
|
||||
|
||||
const optionsReducer = (
|
||||
state = { isUpdating: false, requestingErrors: {} },
|
||||
{ type, options, error, isUpdating, name }
|
||||
) => {
|
||||
switch ( type ) {
|
||||
case TYPES.RECEIVE_OPTIONS:
|
||||
state = {
|
||||
...state,
|
||||
...options,
|
||||
};
|
||||
break;
|
||||
case TYPES.SET_IS_UPDATING:
|
||||
state = {
|
||||
...state,
|
||||
isUpdating,
|
||||
};
|
||||
break;
|
||||
case TYPES.SET_REQUESTING_ERROR:
|
||||
state = {
|
||||
...state,
|
||||
requestingErrors: {
|
||||
[ name ]: error,
|
||||
},
|
||||
};
|
||||
break;
|
||||
case TYPES.SET_UPDATING_ERROR:
|
||||
state = {
|
||||
...state,
|
||||
error,
|
||||
updatingError: error,
|
||||
isUpdating: false,
|
||||
};
|
||||
break;
|
||||
}
|
||||
return state;
|
||||
};
|
||||
|
||||
export default optionsReducer;
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* External Dependencies
|
||||
*/
|
||||
import { batchFetch } from './controls';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { receiveOptions, setRequestingError } from './actions';
|
||||
|
||||
/**
|
||||
* Request an option value.
|
||||
*
|
||||
* @param {string} name - Option name
|
||||
*/
|
||||
export function* getOption( name ) {
|
||||
try {
|
||||
const result = yield batchFetch( name );
|
||||
yield receiveOptions( result );
|
||||
} catch ( error ) {
|
||||
yield setRequestingError( error, name );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* Get option from state tree.
|
||||
*
|
||||
* @param {Object} state - Reducer state
|
||||
* @param {Array} name - Option name
|
||||
*/
|
||||
export const getOption = ( state, name ) => {
|
||||
return state[ name ];
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine if an options request resulted in an error.
|
||||
*
|
||||
* @param {Object} state - Reducer state
|
||||
* @param {string} name - Option name
|
||||
*/
|
||||
export const getOptionsRequestingError = ( state, name ) => {
|
||||
return state.requestingErrors[ name ] || false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine if options are being updated.
|
||||
*
|
||||
* @param {Object} state - Reducer state
|
||||
*/
|
||||
export const isOptionsUpdating = ( state ) => {
|
||||
return state.isUpdating || false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine if an options update resulted in an error.
|
||||
*
|
||||
* @param {Object} state - Reducer state
|
||||
*/
|
||||
export const getOptionsUpdatingError = ( state ) => {
|
||||
return state.updatingError || false;
|
||||
};
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import reducer from '../reducer';
|
||||
import TYPES from '../action-types';
|
||||
|
||||
const defaultState = { isUpdating: false, requestingErrors: {} };
|
||||
|
||||
describe( 'options reducer', () => {
|
||||
it( 'should return a default state', () => {
|
||||
const state = reducer( undefined, {} );
|
||||
expect( state ).toEqual( defaultState );
|
||||
expect( state ).not.toBe( defaultState );
|
||||
} );
|
||||
|
||||
it( 'should handle RECEIVE_OPTIONS', () => {
|
||||
const state = reducer( defaultState, {
|
||||
type: TYPES.RECEIVE_OPTIONS,
|
||||
options: { test_option: 'abc' },
|
||||
} );
|
||||
|
||||
/* eslint-disable dot-notation */
|
||||
expect( state.requestingErrors[ 'test_option' ] ).toBeUndefined();
|
||||
expect( state[ 'test_option' ] ).toBe( 'abc' );
|
||||
/* eslint-enable dot-notation */
|
||||
} );
|
||||
|
||||
it( 'should handle SET_REQUESTING_ERROR', () => {
|
||||
const state = reducer( defaultState, {
|
||||
type: TYPES.SET_REQUESTING_ERROR,
|
||||
error: 'My bad',
|
||||
name: 'test_option'
|
||||
} );
|
||||
|
||||
/* eslint-disable dot-notation */
|
||||
expect( state.requestingErrors[ 'test_option' ] ).toBe( 'My bad' );
|
||||
expect( state[ 'test_option' ] ).toBeUndefined();
|
||||
/* eslint-enable dot-notation */
|
||||
} );
|
||||
|
||||
it( 'should handle SET_UPDATING_ERROR', () => {
|
||||
const state = reducer( defaultState, {
|
||||
type: TYPES.SET_UPDATING_ERROR,
|
||||
error: 'My bad',
|
||||
} );
|
||||
|
||||
expect( state.updatingError ).toBe( 'My bad' );
|
||||
expect( state.isUpdating ).toBe( false );
|
||||
} );
|
||||
|
||||
it( 'should handle SET_IS_UPDATING', () => {
|
||||
const state = reducer( defaultState, {
|
||||
type: TYPES.SET_IS_UPDATING,
|
||||
isUpdating: true,
|
||||
} );
|
||||
|
||||
expect( state.isUpdating ).toBe( true );
|
||||
} );
|
||||
|
||||
} );
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { useRef } from '@wordpress/element';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { STORE_NAME } from './constants';
|
||||
|
||||
export const withOptionsHydration = ( data ) => ( OriginalComponent ) => {
|
||||
return ( props ) => {
|
||||
const dataRef = useRef( data );
|
||||
|
||||
useSelect( ( select, registry ) => {
|
||||
if ( ! dataRef.current ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { isResolving, hasFinishedResolution } = select( STORE_NAME );
|
||||
const {
|
||||
startResolution,
|
||||
finishResolution,
|
||||
receiveOptions,
|
||||
} = registry.dispatch( STORE_NAME );
|
||||
const names = Object.keys( dataRef.current );
|
||||
|
||||
names.forEach( ( name ) => {
|
||||
if (
|
||||
! isResolving( 'getOption', [ name ] ) &&
|
||||
! hasFinishedResolution( 'getOption', [ name ] )
|
||||
) {
|
||||
startResolution( 'getOption', [ name ] );
|
||||
receiveOptions( { [ name ]: dataRef.current[ name ] } );
|
||||
finishResolution( 'getOption', [ name ] );
|
||||
}
|
||||
} );
|
||||
}, [] );
|
||||
|
||||
return <OriginalComponent { ...props } />;
|
||||
};
|
||||
};
|
Loading…
Reference in New Issue