Migrate @woocommerce/data settings store to TS (#34184)
* Migrate wc.data.settings to TS * Correct data.settings type * Fix wc admin client type errors * Add changelog * Add changelog * Update types * Update RawSetting type
This commit is contained in:
parent
3bbee139ed
commit
af97aaf410
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Migrate setting store to TS
|
|
@ -4,6 +4,6 @@ const TYPES = {
|
|||
CLEAR_SETTINGS: 'CLEAR_SETTINGS',
|
||||
SET_IS_REQUESTING: 'SET_IS_REQUESTING',
|
||||
CLEAR_IS_DIRTY: 'CLEAR_IS_DIRTY',
|
||||
};
|
||||
} as const;
|
||||
|
||||
export default TYPES;
|
|
@ -6,6 +6,7 @@ import { __ } from '@wordpress/i18n';
|
|||
import { apiFetch, select } from '@wordpress/data-controls';
|
||||
import { controls } from '@wordpress/data';
|
||||
import { concat } from 'lodash';
|
||||
import { DispatchFromMap } from '@automattic/data-stores';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -13,12 +14,17 @@ import { concat } from 'lodash';
|
|||
import { NAMESPACE } from '../constants';
|
||||
import { STORE_NAME } from './constants';
|
||||
import TYPES from './action-types';
|
||||
import { Settings } from './types';
|
||||
|
||||
// Can be removed in WP 5.9, wp.data is supported in >5.7.
|
||||
const resolveSelect =
|
||||
controls && controls.resolveSelect ? controls.resolveSelect : select;
|
||||
|
||||
export function updateSettingsForGroup( group, data, time = new Date() ) {
|
||||
export function updateSettingsForGroup(
|
||||
group: string,
|
||||
data: Settings,
|
||||
time = new Date()
|
||||
) {
|
||||
return {
|
||||
type: TYPES.UPDATE_SETTINGS_FOR_GROUP,
|
||||
group,
|
||||
|
@ -27,7 +33,12 @@ export function updateSettingsForGroup( group, data, time = new Date() ) {
|
|||
};
|
||||
}
|
||||
|
||||
export function updateErrorForGroup( group, data, error, time = new Date() ) {
|
||||
export function updateErrorForGroup(
|
||||
group: string,
|
||||
data: Settings | null,
|
||||
error: unknown,
|
||||
time = new Date()
|
||||
) {
|
||||
return {
|
||||
type: TYPES.UPDATE_ERROR_FOR_GROUP,
|
||||
group,
|
||||
|
@ -37,7 +48,7 @@ export function updateErrorForGroup( group, data, error, time = new Date() ) {
|
|||
};
|
||||
}
|
||||
|
||||
export function setIsRequesting( group, isRequesting ) {
|
||||
export function setIsRequesting( group: string, isRequesting: boolean ) {
|
||||
return {
|
||||
type: TYPES.SET_IS_REQUESTING,
|
||||
group,
|
||||
|
@ -45,25 +56,23 @@ export function setIsRequesting( group, isRequesting ) {
|
|||
};
|
||||
}
|
||||
|
||||
export function clearIsDirty( group ) {
|
||||
export function clearIsDirty( group: string ) {
|
||||
return {
|
||||
type: TYPES.CLEAR_IS_DIRTY,
|
||||
group,
|
||||
};
|
||||
}
|
||||
|
||||
// allows updating and persisting immediately in one action.
|
||||
export function* updateAndPersistSettingsForGroup( group, data ) {
|
||||
yield updateSettingsForGroup( group, data );
|
||||
yield* persistSettingsForGroup( group );
|
||||
}
|
||||
|
||||
// this would replace setSettingsForGroup
|
||||
export function* persistSettingsForGroup( group ) {
|
||||
export function* persistSettingsForGroup( group: string ) {
|
||||
// first dispatch the is persisting action
|
||||
yield setIsRequesting( group, true );
|
||||
// get all dirty keys with select control
|
||||
const dirtyKeys = yield resolveSelect( STORE_NAME, 'getDirtyKeys', group );
|
||||
const dirtyKeys: string[] = yield resolveSelect(
|
||||
STORE_NAME,
|
||||
'getDirtyKeys',
|
||||
group
|
||||
);
|
||||
// if there is nothing dirty, bail
|
||||
if ( dirtyKeys.length === 0 ) {
|
||||
yield setIsRequesting( group, false );
|
||||
|
@ -71,22 +80,27 @@ export function* persistSettingsForGroup( group ) {
|
|||
}
|
||||
|
||||
// get data slice for keys
|
||||
const dirtyData = yield resolveSelect(
|
||||
const dirtyData: {
|
||||
[ key: string ]: Record< string, unknown >;
|
||||
} = yield resolveSelect(
|
||||
STORE_NAME,
|
||||
'getSettingsForGroup',
|
||||
group,
|
||||
dirtyKeys
|
||||
);
|
||||
const url = `${ NAMESPACE }/settings/${ group }/batch`;
|
||||
|
||||
const update = dirtyKeys.reduce( ( updates, key ) => {
|
||||
const update = dirtyKeys.reduce< Array< { id: string; value: unknown } > >(
|
||||
( updates, key ) => {
|
||||
const u = Object.keys( dirtyData[ key ] ).map( ( k ) => {
|
||||
return { id: k, value: dirtyData[ key ][ k ] };
|
||||
} );
|
||||
|
||||
return concat( updates, u );
|
||||
}, [] );
|
||||
},
|
||||
[]
|
||||
);
|
||||
try {
|
||||
const results = yield apiFetch( {
|
||||
const results: unknown = yield apiFetch( {
|
||||
path: url,
|
||||
method: 'POST',
|
||||
data: { update },
|
||||
|
@ -112,8 +126,30 @@ export function* persistSettingsForGroup( group ) {
|
|||
}
|
||||
}
|
||||
|
||||
// allows updating and persisting immediately in one action.
|
||||
export function* updateAndPersistSettingsForGroup(
|
||||
group: string,
|
||||
data: Settings
|
||||
) {
|
||||
yield updateSettingsForGroup( group, data );
|
||||
yield* persistSettingsForGroup( group );
|
||||
}
|
||||
|
||||
export function clearSettings() {
|
||||
return {
|
||||
type: TYPES.CLEAR_SETTINGS,
|
||||
};
|
||||
}
|
||||
|
||||
export type Actions = ReturnType<
|
||||
| typeof updateSettingsForGroup
|
||||
| typeof updateErrorForGroup
|
||||
| typeof setIsRequesting
|
||||
| typeof clearIsDirty
|
||||
| typeof clearSettings
|
||||
>;
|
||||
|
||||
export type ActionDispatchers = DispatchFromMap< {
|
||||
createProduct: typeof persistSettingsForGroup;
|
||||
updateProduct: typeof updateAndPersistSettingsForGroup;
|
||||
} >;
|
|
@ -1 +1 @@
|
|||
export const STORE_NAME = 'wc/admin/settings';
|
||||
export const STORE_NAME = 'wc/admin/settings' as const;
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
|
||||
import { registerStore } from '@wordpress/data';
|
||||
import { controls } from '@wordpress/data-controls';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { STORE_NAME } from './constants';
|
||||
import * as selectors from './selectors';
|
||||
import * as actions from './actions';
|
||||
import * as resolvers from './resolvers';
|
||||
import reducer from './reducer';
|
||||
|
||||
registerStore( STORE_NAME, {
|
||||
reducer,
|
||||
actions,
|
||||
controls,
|
||||
selectors,
|
||||
resolvers,
|
||||
} );
|
||||
|
||||
export const SETTINGS_STORE_NAME = STORE_NAME;
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
|
||||
import { registerStore } from '@wordpress/data';
|
||||
import { controls } from '@wordpress/data-controls';
|
||||
import { Reducer } from 'redux';
|
||||
import { SelectFromMap, DispatchFromMap } from '@automattic/data-stores';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { WPDataSelectors } from '../types';
|
||||
import { STORE_NAME } from './constants';
|
||||
import * as selectors from './selectors';
|
||||
import * as actions from './actions';
|
||||
import * as resolvers from './resolvers';
|
||||
import reducer, { State } from './reducer';
|
||||
import { SettingsState } from './types';
|
||||
export * from './types';
|
||||
export type { State };
|
||||
|
||||
registerStore< State >( STORE_NAME, {
|
||||
reducer: reducer as Reducer< SettingsState >,
|
||||
actions,
|
||||
controls,
|
||||
selectors,
|
||||
resolvers,
|
||||
} );
|
||||
|
||||
export const SETTINGS_STORE_NAME = STORE_NAME;
|
||||
|
||||
declare module '@wordpress/data' {
|
||||
function dispatch(
|
||||
key: typeof STORE_NAME
|
||||
): DispatchFromMap< typeof actions >;
|
||||
function select(
|
||||
key: typeof STORE_NAME
|
||||
): SelectFromMap< typeof selectors > & WPDataSelectors;
|
||||
}
|
|
@ -2,16 +2,31 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { union } from 'lodash';
|
||||
import { Reducer } from 'redux';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import TYPES from './action-types';
|
||||
import { getResourceName } from '../utils';
|
||||
import { Actions } from './actions';
|
||||
import { Settings, SettingsState } from './types';
|
||||
|
||||
const updateGroupDataInNewState = (
|
||||
newState,
|
||||
{ group, groupIds, data, time, error }
|
||||
newState: SettingsState,
|
||||
{
|
||||
group,
|
||||
groupIds,
|
||||
data,
|
||||
time,
|
||||
error,
|
||||
}: {
|
||||
group: string;
|
||||
groupIds: string[];
|
||||
data: Settings;
|
||||
time: Date;
|
||||
error: unknown;
|
||||
}
|
||||
) => {
|
||||
groupIds.forEach( ( id ) => {
|
||||
newState[ getResourceName( group, id ) ] = {
|
||||
|
@ -23,33 +38,35 @@ const updateGroupDataInNewState = (
|
|||
return newState;
|
||||
};
|
||||
|
||||
const receiveSettings = (
|
||||
state = {},
|
||||
{ type, group, data, error, time, isRequesting }
|
||||
) => {
|
||||
const reducer: Reducer< SettingsState, Actions > = ( state = {}, action ) => {
|
||||
const newState = {};
|
||||
switch ( type ) {
|
||||
switch ( action.type ) {
|
||||
case TYPES.SET_IS_REQUESTING:
|
||||
state = {
|
||||
...state,
|
||||
[ group ]: {
|
||||
...state[ group ],
|
||||
isRequesting,
|
||||
[ action.group ]: {
|
||||
...state[ action.group ],
|
||||
isRequesting: action.isRequesting,
|
||||
},
|
||||
};
|
||||
break;
|
||||
case TYPES.CLEAR_IS_DIRTY:
|
||||
state = {
|
||||
...state,
|
||||
[ group ]: {
|
||||
...state[ group ],
|
||||
[ action.group ]: {
|
||||
...state[ action.group ],
|
||||
dirty: [],
|
||||
},
|
||||
};
|
||||
break;
|
||||
case TYPES.UPDATE_SETTINGS_FOR_GROUP:
|
||||
case TYPES.UPDATE_ERROR_FOR_GROUP:
|
||||
const { data, group, time } = action;
|
||||
const groupIds = data ? Object.keys( data ) : [];
|
||||
const error =
|
||||
action.type === TYPES.UPDATE_ERROR_FOR_GROUP
|
||||
? action.error
|
||||
: null;
|
||||
if ( data === null ) {
|
||||
state = {
|
||||
...state,
|
||||
|
@ -60,12 +77,15 @@ const receiveSettings = (
|
|||
},
|
||||
};
|
||||
} else {
|
||||
const stateGroup = state[ group ];
|
||||
state = {
|
||||
...state,
|
||||
[ group ]: {
|
||||
data:
|
||||
state[ group ] && state[ group ].data
|
||||
? [ ...state[ group ].data, ...groupIds ]
|
||||
stateGroup &&
|
||||
stateGroup.data &&
|
||||
Array.isArray( stateGroup.data )
|
||||
? [ ...stateGroup.data, ...groupIds ]
|
||||
: groupIds,
|
||||
error,
|
||||
lastReceived: time,
|
||||
|
@ -91,4 +111,5 @@ const receiveSettings = (
|
|||
return state;
|
||||
};
|
||||
|
||||
export default receiveSettings;
|
||||
export type State = ReturnType< typeof reducer >;
|
||||
export default reducer;
|
|
@ -1,48 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import {
|
||||
apiFetch,
|
||||
dispatch as depreciatedDispatch,
|
||||
} from '@wordpress/data-controls';
|
||||
import { controls } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { NAMESPACE } from '../constants';
|
||||
import { STORE_NAME } from './constants';
|
||||
import { updateSettingsForGroup, updateErrorForGroup } from './actions';
|
||||
|
||||
// Can be removed in WP 5.9.
|
||||
const dispatch =
|
||||
controls && controls.dispatch ? controls.dispatch : depreciatedDispatch;
|
||||
|
||||
function settingsToSettingsResource( settings ) {
|
||||
return settings.reduce( ( resource, setting ) => {
|
||||
resource[ setting.id ] = setting.value;
|
||||
return resource;
|
||||
}, {} );
|
||||
}
|
||||
|
||||
export function* getSettings( group ) {
|
||||
yield dispatch( STORE_NAME, 'setIsRequesting', group, true );
|
||||
|
||||
try {
|
||||
const url = NAMESPACE + '/settings/' + group;
|
||||
const results = yield apiFetch( {
|
||||
path: url,
|
||||
method: 'GET',
|
||||
} );
|
||||
|
||||
const resource = settingsToSettingsResource( results );
|
||||
|
||||
return updateSettingsForGroup( group, { [ group ]: resource } );
|
||||
} catch ( error ) {
|
||||
return updateErrorForGroup( group, null, error.message );
|
||||
}
|
||||
}
|
||||
|
||||
export function* getSettingsForGroup( group ) {
|
||||
return getSettings( group );
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import {
|
||||
apiFetch,
|
||||
dispatch as depreciatedDispatch,
|
||||
} from '@wordpress/data-controls';
|
||||
import { controls } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { NAMESPACE } from '../constants';
|
||||
import { STORE_NAME } from './constants';
|
||||
import { updateSettingsForGroup, updateErrorForGroup } from './actions';
|
||||
import { isRestApiError } from '../types';
|
||||
|
||||
// Can be removed in WP 5.9.
|
||||
const dispatch =
|
||||
controls && controls.dispatch ? controls.dispatch : depreciatedDispatch;
|
||||
|
||||
// [class-wc-rest-setting-options-controller.php](https://github.com/woocommerce/woocommerce/blob/28926968bdcd2b504e16761a483388f85ee0c151/plugins/woocommerce/includes/rest-api/Controllers/Version3/class-wc-rest-setting-options-controller.php#L158-L248)
|
||||
type RawSetting = {
|
||||
id: string;
|
||||
group_id: string;
|
||||
label: string;
|
||||
description: string;
|
||||
tip?: string;
|
||||
type:
|
||||
| 'text'
|
||||
| 'email'
|
||||
| 'number'
|
||||
| 'color'
|
||||
| 'password'
|
||||
| 'textarea'
|
||||
| 'select'
|
||||
| 'multiselect'
|
||||
| 'radio'
|
||||
| 'image_width'
|
||||
| 'checkbox';
|
||||
default: unknown;
|
||||
value: unknown;
|
||||
options: {
|
||||
[ key: string ]: string;
|
||||
};
|
||||
placeholder?: string;
|
||||
};
|
||||
|
||||
function settingsToSettingsResource( settings: RawSetting[] ) {
|
||||
return settings.reduce< {
|
||||
[ id: string ]: unknown;
|
||||
} >( ( resource, setting ) => {
|
||||
resource[ setting.id ] = setting.value;
|
||||
return resource;
|
||||
}, {} );
|
||||
}
|
||||
|
||||
export function* getSettings( group: string ) {
|
||||
yield dispatch( STORE_NAME, 'setIsRequesting', group, true );
|
||||
try {
|
||||
const url = NAMESPACE + '/settings/' + group;
|
||||
const results: RawSetting[] = yield apiFetch( {
|
||||
path: url,
|
||||
method: 'GET',
|
||||
} );
|
||||
const resource = settingsToSettingsResource( results );
|
||||
return updateSettingsForGroup( group, { [ group ]: resource } );
|
||||
} catch ( error ) {
|
||||
if ( error instanceof Error || isRestApiError( error ) ) {
|
||||
return updateErrorForGroup( group, null, error.message );
|
||||
}
|
||||
throw `Unexpected error ${ error }`;
|
||||
}
|
||||
}
|
||||
|
||||
export function* getSettingsForGroup( group: string ) {
|
||||
return getSettings( group );
|
||||
}
|
|
@ -2,8 +2,9 @@
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { getResourceName, getResourcePrefix } from '../utils';
|
||||
import { SettingsState, Settings } from './types';
|
||||
|
||||
export const getSettingsGroupNames = ( state ) => {
|
||||
export const getSettingsGroupNames = ( state: SettingsState ) => {
|
||||
const groupNames = new Set(
|
||||
Object.keys( state ).map( ( resourceName ) => {
|
||||
return getResourcePrefix( resourceName );
|
||||
|
@ -12,10 +13,10 @@ export const getSettingsGroupNames = ( state ) => {
|
|||
return [ ...groupNames ];
|
||||
};
|
||||
|
||||
export const getSettings = ( state, group ) => {
|
||||
const settings = {};
|
||||
export const getSettings = ( state: SettingsState, group: string ) => {
|
||||
const settings: Settings = {};
|
||||
const settingIds = ( state[ group ] && state[ group ].data ) || [];
|
||||
if ( settingIds.length === 0 ) {
|
||||
if ( ! Array.isArray( settingIds ) || settingIds.length === 0 ) {
|
||||
return settings;
|
||||
}
|
||||
settingIds.forEach( ( id ) => {
|
||||
|
@ -24,11 +25,15 @@ export const getSettings = ( state, group ) => {
|
|||
return settings;
|
||||
};
|
||||
|
||||
export const getDirtyKeys = ( state, group ) => {
|
||||
export const getDirtyKeys = ( state: SettingsState, group: string ) => {
|
||||
return state[ group ].dirty || [];
|
||||
};
|
||||
|
||||
export const getIsDirty = ( state, group, keys = [] ) => {
|
||||
export const getIsDirty = (
|
||||
state: SettingsState,
|
||||
group: string,
|
||||
keys: string[] = []
|
||||
) => {
|
||||
const dirtyMap = getDirtyKeys( state, group );
|
||||
// if empty array bail
|
||||
if ( dirtyMap.length === 0 ) {
|
||||
|
@ -39,15 +44,22 @@ export const getIsDirty = ( state, group, keys = [] ) => {
|
|||
return keys.some( ( key ) => dirtyMap.includes( key ) );
|
||||
};
|
||||
|
||||
export const getSettingsForGroup = ( state, group, keys ) => {
|
||||
export const getSettingsForGroup = (
|
||||
state: SettingsState,
|
||||
group: string,
|
||||
keys: string[]
|
||||
) => {
|
||||
const allSettings = getSettings( state, group );
|
||||
return keys.reduce( ( accumulator, key ) => {
|
||||
return keys.reduce< Settings >( ( accumulator, key ) => {
|
||||
accumulator[ key ] = allSettings[ key ] || {};
|
||||
return accumulator;
|
||||
}, {} );
|
||||
};
|
||||
|
||||
export const isUpdateSettingsRequesting = ( state, group ) => {
|
||||
export const isUpdateSettingsRequesting = (
|
||||
state: SettingsState,
|
||||
group: string
|
||||
) => {
|
||||
return state[ group ] && Boolean( state[ group ].isRequesting );
|
||||
};
|
||||
|
||||
|
@ -70,11 +82,12 @@ export const isUpdateSettingsRequesting = ( state, group ) => {
|
|||
* name.
|
||||
*/
|
||||
export function getSetting(
|
||||
state,
|
||||
group,
|
||||
name,
|
||||
state: SettingsState,
|
||||
group: string,
|
||||
name: string,
|
||||
fallback = false,
|
||||
filter = ( val ) => val
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- _fallback in default filter is unused.
|
||||
filter = ( val: unknown, _fallback: unknown | boolean ) => val
|
||||
) {
|
||||
const resourceName = getResourceName( group, name );
|
||||
const value =
|
||||
|
@ -82,15 +95,22 @@ export function getSetting(
|
|||
return filter( value, fallback );
|
||||
}
|
||||
|
||||
export const getLastSettingsErrorForGroup = ( state, group ) => {
|
||||
export const getLastSettingsErrorForGroup = (
|
||||
state: SettingsState,
|
||||
group: string
|
||||
) => {
|
||||
const settingsIds = state[ group ].data;
|
||||
if ( settingsIds.length === 0 ) {
|
||||
if ( ! Array.isArray( settingsIds ) || settingsIds.length === 0 ) {
|
||||
return state[ group ].error;
|
||||
}
|
||||
return [ ...settingsIds ].pop().error;
|
||||
};
|
||||
|
||||
export const getSettingsError = ( state, group, id ) => {
|
||||
export const getSettingsError = (
|
||||
state: SettingsState,
|
||||
group: string,
|
||||
id: string
|
||||
) => {
|
||||
if ( ! id ) {
|
||||
return ( state[ group ] && state[ group ].error ) || false;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
export type Settings = {
|
||||
[ key: string ]: unknown;
|
||||
} & {
|
||||
general?: {
|
||||
[ key: string ]: string;
|
||||
};
|
||||
tax?: {
|
||||
[ key: string ]: string;
|
||||
};
|
||||
};
|
||||
|
||||
export type SettingsState = {
|
||||
[ key: string ]: {
|
||||
data?: unknown;
|
||||
lastReceived?: Date;
|
||||
error?: unknown;
|
||||
isRequesting?: boolean;
|
||||
dirty?: string[];
|
||||
};
|
||||
};
|
|
@ -9,7 +9,7 @@ import { useCallback } from '@wordpress/element';
|
|||
*/
|
||||
import { STORE_NAME } from './constants';
|
||||
|
||||
export const useSettings = ( group, settingsKeys = [] ) => {
|
||||
export const useSettings = ( group: string, settingsKeys: string[] = [] ) => {
|
||||
const { requestedSettings, settingsError, isRequesting, isDirty } =
|
||||
useSelect(
|
||||
( select ) => {
|
|
@ -2,20 +2,22 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { createHigherOrderComponent } from '@wordpress/compose';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
import { useSelect, select as wpSelect } from '@wordpress/data';
|
||||
import { createElement, useRef } from '@wordpress/element';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { STORE_NAME } from './constants';
|
||||
import { Settings } from './types';
|
||||
|
||||
export const withSettingsHydration = ( group, settings ) =>
|
||||
createHigherOrderComponent(
|
||||
export const withSettingsHydration = ( group: string, settings: Settings ) =>
|
||||
createHigherOrderComponent< Record< string, unknown > >(
|
||||
( OriginalComponent ) => ( props ) => {
|
||||
const settingsRef = useRef( settings );
|
||||
|
||||
useSelect( ( select, registry ) => {
|
||||
// @ts-expect-error registry is not defined in the wp.data typings
|
||||
useSelect( ( select: typeof wpSelect, registry ) => {
|
||||
if ( ! settingsRef.current ) {
|
||||
return;
|
||||
}
|
|
@ -12,7 +12,7 @@ import { fetchWithHeaders } from './controls';
|
|||
|
||||
export function getResourceName(
|
||||
prefix: string,
|
||||
identifier: Record< string, unknown >
|
||||
identifier: Record< string, unknown > | string
|
||||
) {
|
||||
const identifierString = JSON.stringify(
|
||||
identifier,
|
||||
|
|
|
@ -25,11 +25,7 @@ const ShippingRecommendations: React.FC = () => {
|
|||
isJetpackConnected,
|
||||
isSellingDigitalProductsOnly,
|
||||
} = useSelect( ( select ) => {
|
||||
const settings = select( SETTINGS_STORE_NAME ).getSettings< {
|
||||
general?: {
|
||||
woocommerce_default_country: string;
|
||||
};
|
||||
} >( 'general' );
|
||||
const settings = select( SETTINGS_STORE_NAME ).getSettings( 'general' );
|
||||
|
||||
const {
|
||||
getActivePlugins,
|
||||
|
|
|
@ -64,9 +64,7 @@ export const Products = () => {
|
|||
|
||||
const { isStoreInUS } = useSelect( ( select ) => {
|
||||
const { getSettings } = select( SETTINGS_STORE_NAME );
|
||||
const { general: settings = {} } = getSettings< {
|
||||
general?: { [ key: string ]: unknown };
|
||||
} >( 'general' );
|
||||
const { general: settings = {} } = getSettings( 'general' );
|
||||
|
||||
const country =
|
||||
typeof settings.woocommerce_default_country === 'string'
|
||||
|
|
|
@ -10,7 +10,7 @@ import { useSelect, useDispatch } from '@wordpress/data';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { getCountryCode } from '~/dashboard/utils';
|
||||
import { hasCompleteAddress, SettingsSelector } from '../../tax/utils';
|
||||
import { hasCompleteAddress } from '../../tax/utils';
|
||||
import { default as StoreLocationForm } from '~/tasks/fills/steps/location';
|
||||
|
||||
export const StoreLocation: React.FC< {
|
||||
|
@ -21,9 +21,8 @@ export const StoreLocation: React.FC< {
|
|||
const { updateAndPersistSettingsForGroup } =
|
||||
useDispatch( SETTINGS_STORE_NAME );
|
||||
const { generalSettings, isResolving } = useSelect( ( select ) => {
|
||||
const { getSettings, hasFinishedResolution } = select(
|
||||
SETTINGS_STORE_NAME
|
||||
) as SettingsSelector;
|
||||
const { getSettings, hasFinishedResolution } =
|
||||
select( SETTINGS_STORE_NAME );
|
||||
|
||||
return {
|
||||
generalSettings: getSettings( 'general' )?.general,
|
||||
|
@ -34,7 +33,7 @@ export const StoreLocation: React.FC< {
|
|||
} );
|
||||
|
||||
useEffect( () => {
|
||||
if ( isResolving || ! hasCompleteAddress( generalSettings ) ) {
|
||||
if ( isResolving || ! hasCompleteAddress( generalSettings || {} ) ) {
|
||||
return;
|
||||
}
|
||||
onLocationComplete();
|
||||
|
|
|
@ -14,15 +14,12 @@ import { compose } from '@wordpress/compose';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { SettingsSelector } from '../tax/utils';
|
||||
import { ShippingRecommendation } from './shipping-recommendation';
|
||||
import { TaskProps } from './types';
|
||||
|
||||
const ShippingRecommendationWrapper = compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getSettings } = select(
|
||||
SETTINGS_STORE_NAME
|
||||
) as SettingsSelector;
|
||||
const { getSettings } = select( SETTINGS_STORE_NAME );
|
||||
const { hasFinishedResolution } = select( OPTIONS_STORE_NAME );
|
||||
const { getActivePlugins } = select( PLUGINS_STORE_NAME );
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import { useSelect, useDispatch } from '@wordpress/data';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { getCountryCode } from '~/dashboard/utils';
|
||||
import { hasCompleteAddress, SettingsSelector } from '../utils';
|
||||
import { hasCompleteAddress } from '../utils';
|
||||
import { default as StoreLocationForm } from '~/tasks/fills/steps/location';
|
||||
|
||||
export const StoreLocation: React.FC< {
|
||||
|
@ -21,9 +21,8 @@ export const StoreLocation: React.FC< {
|
|||
const { updateAndPersistSettingsForGroup } =
|
||||
useDispatch( SETTINGS_STORE_NAME );
|
||||
const { generalSettings, isResolving } = useSelect( ( select ) => {
|
||||
const { getSettings, hasFinishedResolution } = select(
|
||||
SETTINGS_STORE_NAME
|
||||
) as SettingsSelector;
|
||||
const { getSettings, hasFinishedResolution } =
|
||||
select( SETTINGS_STORE_NAME );
|
||||
|
||||
return {
|
||||
generalSettings: getSettings( 'general' )?.general,
|
||||
|
@ -34,7 +33,7 @@ export const StoreLocation: React.FC< {
|
|||
} );
|
||||
|
||||
useEffect( () => {
|
||||
if ( isResolving || ! hasCompleteAddress( generalSettings ) ) {
|
||||
if ( isResolving || ! hasCompleteAddress( generalSettings || {} ) ) {
|
||||
return;
|
||||
}
|
||||
nextStep();
|
||||
|
|
|
@ -24,11 +24,7 @@ import { WooOnboardingTask } from '@woocommerce/onboarding';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import {
|
||||
redirectToTaxSettings,
|
||||
SettingsSelector,
|
||||
supportsAvalara,
|
||||
} from './utils';
|
||||
import { redirectToTaxSettings, supportsAvalara } from './utils';
|
||||
import { Card as AvalaraCard } from './avalara/card';
|
||||
import { Card as WooCommerceTaxCard } from './woocommerce-tax/card';
|
||||
import { createNoticesFromResponse } from '../../../lib/notices';
|
||||
|
@ -59,10 +55,8 @@ const Tax: React.FC< TaxProps > = ( { onComplete, query, task } ) => {
|
|||
useDispatch( SETTINGS_STORE_NAME );
|
||||
const { generalSettings, isResolving, taxSettings } = useSelect(
|
||||
( select ) => {
|
||||
const { getSettings, hasFinishedResolution } = select(
|
||||
SETTINGS_STORE_NAME
|
||||
) as SettingsSelector;
|
||||
|
||||
const { getSettings, hasFinishedResolution } =
|
||||
select( SETTINGS_STORE_NAME );
|
||||
return {
|
||||
generalSettings: getSettings( 'general' ).general,
|
||||
isResolving: ! hasFinishedResolution( 'getSettings', [
|
||||
|
@ -75,7 +69,7 @@ const Tax: React.FC< TaxProps > = ( { onComplete, query, task } ) => {
|
|||
|
||||
const onManual = useCallback( async () => {
|
||||
setIsPending( true );
|
||||
if ( generalSettings.woocommerce_calc_taxes !== 'yes' ) {
|
||||
if ( generalSettings?.woocommerce_calc_taxes !== 'yes' ) {
|
||||
updateAndPersistSettingsForGroup( 'tax', {
|
||||
tax: {
|
||||
...taxSettings,
|
||||
|
@ -88,7 +82,6 @@ const Tax: React.FC< TaxProps > = ( { onComplete, query, task } ) => {
|
|||
woocommerce_calc_taxes: 'yes',
|
||||
},
|
||||
} )
|
||||
// @ts-expect-error updateAndPersistSettingsForGroup returns a Promise, but it is not typed in source.
|
||||
.then( () => redirectToTaxSettings() )
|
||||
.catch( ( error: unknown ) => {
|
||||
setIsPending( false );
|
||||
|
|
|
@ -12,15 +12,13 @@ import { useSelect } from '@wordpress/data';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { SettingsSelector, TaxChildProps } from '../utils';
|
||||
import { TaxChildProps } from '../utils';
|
||||
|
||||
export const Configure: React.FC<
|
||||
Pick< TaxChildProps, 'isPending' | 'onManual' >
|
||||
> = ( { isPending, onManual } ) => {
|
||||
const { generalSettings } = useSelect( ( select ) => {
|
||||
const { getSettings } = select(
|
||||
SETTINGS_STORE_NAME
|
||||
) as SettingsSelector;
|
||||
const { getSettings } = select( SETTINGS_STORE_NAME );
|
||||
|
||||
return {
|
||||
generalSettings: getSettings( 'general' )?.general,
|
||||
|
@ -41,7 +39,7 @@ export const Configure: React.FC<
|
|||
{ __( 'Configure', 'woocommerce' ) }
|
||||
</Button>
|
||||
<p>
|
||||
{ generalSettings.woocommerce_calc_taxes !== 'yes' &&
|
||||
{ generalSettings?.woocommerce_calc_taxes !== 'yes' &&
|
||||
interpolateComponents( {
|
||||
mixedString: __(
|
||||
/*eslint-disable max-len*/
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { getAdminLink } from '@woocommerce/settings';
|
||||
import { WPDataSelectors, TaskType } from '@woocommerce/data';
|
||||
import { TaskType } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Plugins required to automate taxes.
|
||||
|
@ -17,11 +17,9 @@ export const AUTOMATION_PLUGINS = [ 'jetpack', 'woocommerce-services' ];
|
|||
* @param {Object} generalSettings.woocommerce_default_country Store default country.
|
||||
* @param {Object} generalSettings.woocommerce_store_postcode Store postal code.
|
||||
*/
|
||||
export const hasCompleteAddress = ( generalSettings: {
|
||||
woocommerce_store_address?: string;
|
||||
woocommerce_default_country?: string;
|
||||
woocommerce_store_postcode?: string;
|
||||
} ): boolean => {
|
||||
export const hasCompleteAddress = (
|
||||
generalSettings: Record< string, string >
|
||||
): boolean => {
|
||||
const {
|
||||
woocommerce_store_address: storeAddress,
|
||||
woocommerce_default_country: defaultCountry,
|
||||
|
@ -39,22 +37,6 @@ export const redirectToTaxSettings = (): void => {
|
|||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Types for settings selectors.
|
||||
*/
|
||||
export type SettingsSelector = WPDataSelectors & {
|
||||
getSettings: ( type: string ) => {
|
||||
general: {
|
||||
woocommerce_default_country?: string;
|
||||
woocommerce_calc_taxes?: string;
|
||||
};
|
||||
tax: { [ key: string ]: string };
|
||||
};
|
||||
getOption: ( type: string ) => {
|
||||
tos_accepted?: boolean;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Types for child tax components.
|
||||
*/
|
||||
|
|
|
@ -13,7 +13,6 @@ import { PLUGINS_STORE_NAME, SETTINGS_STORE_NAME } from '@woocommerce/data';
|
|||
import {
|
||||
AUTOMATION_PLUGINS,
|
||||
hasCompleteAddress,
|
||||
SettingsSelector,
|
||||
TaxChildProps,
|
||||
} from '../utils';
|
||||
import { AutomatedTaxes } from './automated-taxes';
|
||||
|
@ -31,9 +30,7 @@ export const WooCommerceTax: React.FC< TaxChildProps > = ( {
|
|||
isResolving,
|
||||
pluginsToActivate,
|
||||
} = useSelect( ( select ) => {
|
||||
const { getSettings } = select(
|
||||
SETTINGS_STORE_NAME
|
||||
) as SettingsSelector;
|
||||
const { getSettings } = select( SETTINGS_STORE_NAME );
|
||||
const { getActivePlugins, hasFinishedResolution } =
|
||||
select( PLUGINS_STORE_NAME );
|
||||
const activePlugins = getActivePlugins();
|
||||
|
@ -55,7 +52,7 @@ export const WooCommerceTax: React.FC< TaxChildProps > = ( {
|
|||
|
||||
const canAutomateTaxes = () => {
|
||||
return (
|
||||
hasCompleteAddress( generalSettings ) &&
|
||||
hasCompleteAddress( generalSettings || {} ) &&
|
||||
! pluginsToActivate.length &&
|
||||
isJetpackConnected
|
||||
);
|
||||
|
|
|
@ -15,7 +15,7 @@ import { useSelect } from '@wordpress/data';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { AUTOMATION_PLUGINS, SettingsSelector } from '../utils';
|
||||
import { AUTOMATION_PLUGINS } from '../utils';
|
||||
import { Connect } from './connect';
|
||||
import { Plugins } from './plugins';
|
||||
import { StoreLocation } from '../components/store-location';
|
||||
|
@ -48,9 +48,7 @@ export const Setup: React.FC< SetupProps > = ( {
|
|||
[]
|
||||
);
|
||||
const { activePlugins, isResolving } = useSelect( ( select ) => {
|
||||
const { getSettings } = select(
|
||||
SETTINGS_STORE_NAME
|
||||
) as SettingsSelector;
|
||||
const { getSettings } = select( SETTINGS_STORE_NAME );
|
||||
const { hasFinishedResolution } = select( OPTIONS_STORE_NAME );
|
||||
const { getActivePlugins } = select( PLUGINS_STORE_NAME );
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Fix typescript errors for setting selector
|
Loading…
Reference in New Issue