diff --git a/packages/js/data/src/index.ts b/packages/js/data/src/index.ts index 29cf9b2a4b9..8267b184de1 100644 --- a/packages/js/data/src/index.ts +++ b/packages/js/data/src/index.ts @@ -3,6 +3,70 @@ */ import '@wordpress/core-data'; +// Export store names +export { SETTINGS_STORE_NAME } from './settings'; +export { PLUGINS_STORE_NAME } from './plugins'; +export { ONBOARDING_STORE_NAME } from './onboarding'; +export { USER_STORE_NAME } from './user'; +export { REVIEWS_STORE_NAME } from './reviews'; +export { NOTES_STORE_NAME } from './notes'; +export { REPORTS_STORE_NAME } from './reports'; +export { COUNTRIES_STORE_NAME } from './countries'; +export { NAVIGATION_STORE_NAME } from './navigation'; +export { OPTIONS_STORE_NAME } from './options'; +export { ITEMS_STORE_NAME } from './items'; +export { PAYMENT_GATEWAYS_STORE_NAME } from './payment-gateways'; + +// Export hooks +export { withSettingsHydration } from './settings/with-settings-hydration'; +export { withOnboardingHydration } from './onboarding/with-onboarding-hydration'; +export { withCurrentUserHydration } from './user/with-current-user-hydration'; +export { withNavigationHydration } from './navigation/with-navigation-hydration'; +export { withPluginsHydration } from './plugins/with-plugins-hydration'; +export { + withOptionsHydration, + useOptionsHydration, +} from './options/with-options-hydration'; +export { useSettings } from './settings/use-settings'; +export { useUserPreferences } from './user/use-user-preferences'; +export { useUser } from './user/use-user'; + +// Export utils +export { getVisibleTasks } from './onboarding/utils'; +export { getLeaderboard, searchItemsByString } from './items/utils'; +export { + getFilterQuery, + getSummaryNumbers, + getReportTableData, + getReportTableQuery, + getReportChartData, + getTooltipValueFormat, +} from './reports/utils'; + +// Export constants +export { pluginNames } from './plugins/constants'; +export { EXPORT_STORE_NAME } from './export'; +export { IMPORT_STORE_NAME } from './import'; +export { + MAX_PER_PAGE, + QUERY_DEFAULTS, + NAMESPACE, + WC_ADMIN_NAMESPACE, + WCS_NAMESPACE, + SECOND, + MINUTE, + HOUR, + DAY, + WEEK, + MONTH, +} from './constants'; + +// Export types +export * from './types'; +export * from './countries/types'; +export * from './onboarding/types'; +export * from './plugins/types'; + /** * Internal dependencies */ @@ -18,82 +82,6 @@ import type { REPORTS_STORE_NAME } from './reports'; import type { ITEMS_STORE_NAME } from './items'; import type { COUNTRIES_STORE_NAME } from './countries'; import type { PAYMENT_GATEWAYS_STORE_NAME } from './payment-gateways'; -import { OnboardingSelectors } from './onboarding/selectors'; -import { PaymentSelectors } from './payment-gateways/selectors'; -import { WPDataSelectors } from './types'; -import { PluginSelectors } from './plugins/selectors'; - -export * from './types'; -export { SETTINGS_STORE_NAME } from './settings'; -export { withSettingsHydration } from './settings/with-settings-hydration'; -export { useSettings } from './settings/use-settings'; - -export { PLUGINS_STORE_NAME } from './plugins'; -export type { Plugin } from './plugins/types'; -export type { InstallPluginsResponse } from './plugins/actions'; -export { ActionDispatchers as PluginsStoreActions } from './plugins/actions'; -export { pluginNames } from './plugins/constants'; -export { withPluginsHydration } from './plugins/with-plugins-hydration'; - -export { ONBOARDING_STORE_NAME } from './onboarding'; -export { withOnboardingHydration } from './onboarding/with-onboarding-hydration'; -export { getVisibleTasks } from './onboarding/utils'; -export type { TaskType, TaskListType } from './onboarding/types'; -export type { Extension, ExtensionList } from './onboarding/selectors'; - -export { USER_STORE_NAME } from './user'; -export { withCurrentUserHydration } from './user/with-current-user-hydration'; -export { useUser } from './user/use-user'; -export { useUserPreferences } from './user/use-user-preferences'; - -export { OPTIONS_STORE_NAME } from './options'; -export { - withOptionsHydration, - useOptionsHydration, -} from './options/with-options-hydration'; - -export { REVIEWS_STORE_NAME } from './reviews'; - -export { NOTES_STORE_NAME } from './notes'; - -export { REPORTS_STORE_NAME } from './reports'; - -export { ITEMS_STORE_NAME } from './items'; -export { getLeaderboard, searchItemsByString } from './items/utils'; - -export { COUNTRIES_STORE_NAME } from './countries'; - -export { NAVIGATION_STORE_NAME } from './navigation'; -export { withNavigationHydration } from './navigation/with-navigation-hydration'; - -export { PAYMENT_GATEWAYS_STORE_NAME } from './payment-gateways'; - -export { - getFilterQuery, - getSummaryNumbers, - getReportTableData, - getReportTableQuery, - getReportChartData, - getTooltipValueFormat, -} from './reports/utils'; - -export { - MAX_PER_PAGE, - QUERY_DEFAULTS, - NAMESPACE, - WC_ADMIN_NAMESPACE, - WCS_NAMESPACE, - SECOND, - MINUTE, - HOUR, - DAY, - WEEK, - MONTH, -} from './constants'; - -export { EXPORT_STORE_NAME } from './export'; - -export { IMPORT_STORE_NAME } from './import'; export type WCDataStoreName = | typeof REVIEWS_STORE_NAME @@ -109,6 +97,14 @@ export type WCDataStoreName = | typeof COUNTRIES_STORE_NAME | typeof PAYMENT_GATEWAYS_STORE_NAME; +/** + * Internal dependencies + */ +import { WPDataSelectors } from './types'; +import { PaymentSelectors } from './payment-gateways/selectors'; +import { PluginSelectors } from './plugins/selectors'; +import { OnboardingSelectors } from './onboarding/selectors'; + // As we add types to all the package selectors we can fill out these unknown types with real ones. See one // of the already typed selectors for an example of how you can do this. export type WCSelectorType< T > = T extends typeof REVIEWS_STORE_NAME @@ -140,6 +136,6 @@ export type WCSelectorType< T > = T extends typeof REVIEWS_STORE_NAME export interface WCDataSelector { < T extends WCDataStoreName >( storeName: T ): WCSelectorType< T >; } -export * from './onboarding/selectors'; -export * from './onboarding/types'; -export * from './countries/types'; + +// Other exports +export { ActionDispatchers as PluginsStoreActions } from './plugins/actions'; diff --git a/packages/js/data/src/onboarding/selectors.ts b/packages/js/data/src/onboarding/selectors.ts index 49cc396fab6..b4ed40c07d7 100644 --- a/packages/js/data/src/onboarding/selectors.ts +++ b/packages/js/data/src/onboarding/selectors.ts @@ -6,7 +6,14 @@ import createSelector from 'rememo'; /** * Internal dependencies */ -import { TaskType, TaskListType } from './types'; +import { + TaskType, + TaskListType, + OnboardingState, + ExtensionList, + ProfileItemsState, + Product, +} from './types'; import { WPDataSelectors } from '../types'; import { Plugin } from '../plugins/types'; @@ -22,8 +29,6 @@ export const getProfileItems = ( return state.profileItems || {}; }; -const EMPTY_ARRAY: Product[] = []; - export const getTaskLists = createSelector( ( state: OnboardingState ): TaskListType[] => { return Object.values( state.taskLists ); @@ -88,10 +93,9 @@ export const getEmailPrefill = ( state: OnboardingState ): string => { }; export const getProductTypes = ( state: OnboardingState ): Product[] => { - return state.productTypes || EMPTY_ARRAY; + return state.productTypes || []; }; -// Types export type OnboardingSelectors = { getProfileItems: () => ReturnType< typeof getProfileItems >; getPaymentGatewaySuggestions: () => ReturnType< @@ -106,104 +110,3 @@ export type OnboardingSelectors = { getTaskList: ( id: string ) => ReturnType< typeof getTaskList >; getFreeExtensions: () => ReturnType< typeof getFreeExtensions >; } & WPDataSelectors; - -export type OnboardingState = { - freeExtensions: ExtensionList[]; - profileItems: ProfileItemsState; - taskLists: Record< string, TaskListType >; - paymentMethods: Plugin[]; - productTypes: Product[]; - emailPrefill: string; - // TODO clarify what the error record's type is - errors: Record< string, unknown >; - requesting: Record< string, boolean >; -}; - -export type Industry = { - slug: string; -}; - -export type ProductCount = '0' | '1-10' | '11-100' | '101 - 1000' | '1000+'; - -export type ProductTypeSlug = - | 'physical' - | 'bookings' - | 'download' - | 'memberships' - | 'product-add-ons' - | 'product-bundles' - | 'subscriptions'; - -export type OtherPlatformSlug = - | 'shopify' - | 'bigcommerce' - | 'wix' - | 'amazon' - | 'ebay' - | 'etsy' - | 'squarespace' - | 'other'; - -export type RevenueTypeSlug = - | 'none' - | 'rather-not-say' - | 'up-to-2500' - | '2500-10000' - | '10000-50000' - | '50000-250000' - | 'more-than-250000'; - -export type ProfileItemsState = { - business_extensions: [ ] | null; - completed: boolean | null; - industry: Industry[] | null; - number_employees: string | null; - other_platform: OtherPlatformSlug | null; - other_platform_name: string | null; - product_count: ProductCount | null; - product_types: ProductTypeSlug[] | null; - revenue: RevenueTypeSlug | null; - selling_venues: string | null; - setup_client: boolean | null; - skipped: boolean | null; - theme: string | null; - wccom_connected: boolean | null; - is_agree_marketing: boolean | null; - store_email: string | null; -}; - -export type FieldLocale = { - locale: string; - label: string; -}; - -export type MethodFields = { - name: string; - option?: string; - label?: string; - locales?: FieldLocale[]; - type?: string; - value?: string; -}; - -export type Product = { - default?: boolean; - label: string; - product?: number; -}; - -export type ExtensionList = { - key: string; - title: string; - plugins: Extension[]; -}; - -export type Extension = { - description: string; - key: string; - image_url: string; - manage_url: string; - name: string; - is_built_by_wc: boolean; - is_visible: boolean; -}; diff --git a/packages/js/data/src/onboarding/types.ts b/packages/js/data/src/onboarding/types.ts index 0f51b826452..01d6a97cf01 100644 --- a/packages/js/data/src/onboarding/types.ts +++ b/packages/js/data/src/onboarding/types.ts @@ -1,3 +1,8 @@ +/** + * Internal dependencies + */ +import { Plugin } from '../plugins/types'; + export type TaskType = { actionLabel?: string; actionUrl?: string; @@ -51,3 +56,103 @@ export type TaskListType = { isCollapsible?: boolean; isExpandable?: boolean; }; + +export type OnboardingState = { + freeExtensions: ExtensionList[]; + profileItems: ProfileItemsState; + taskLists: Record< string, TaskListType >; + paymentMethods: Plugin[]; + productTypes: Product[]; + emailPrefill: string; + // TODO clarify what the error record's type is + errors: Record< string, unknown >; + requesting: Record< string, boolean >; +}; + +export type Industry = { + slug: string; +}; + +export type ProductCount = '0' | '1-10' | '11-100' | '101 - 1000' | '1000+'; + +export type ProductTypeSlug = + | 'physical' + | 'bookings' + | 'download' + | 'memberships' + | 'product-add-ons' + | 'product-bundles' + | 'subscriptions'; + +export type OtherPlatformSlug = + | 'shopify' + | 'bigcommerce' + | 'wix' + | 'amazon' + | 'ebay' + | 'etsy' + | 'squarespace' + | 'other'; + +export type RevenueTypeSlug = + | 'none' + | 'rather-not-say' + | 'up-to-2500' + | '2500-10000' + | '10000-50000' + | '50000-250000' + | 'more-than-250000'; + +export type ProfileItemsState = { + business_extensions: [ ] | null; + completed: boolean | null; + industry: Industry[] | null; + number_employees: string | null; + other_platform: OtherPlatformSlug | null; + other_platform_name: string | null; + product_count: ProductCount | null; + product_types: ProductTypeSlug[] | null; + revenue: RevenueTypeSlug | null; + selling_venues: string | null; + setup_client: boolean | null; + skipped: boolean | null; + theme: string | null; + wccom_connected: boolean | null; + is_agree_marketing: boolean | null; + store_email: string | null; +}; + +export type FieldLocale = { + locale: string; + label: string; +}; + +export type MethodFields = { + name: string; + option?: string; + label?: string; + locales?: FieldLocale[]; + type?: string; + value?: string; +}; + +export type Product = { + default?: boolean; + label: string; + product?: number; +}; + +export type ExtensionList = { + key: string; + title: string; + plugins: Extension[]; +}; + +export type Extension = { + description: string; + key: string; + image_url: string; + manage_url: string; + name: string; + is_built_by_wc: boolean; +}; diff --git a/packages/js/data/src/plugins/actions.ts b/packages/js/data/src/plugins/actions.ts index 0bed3ac7d1c..a4a0894d0e5 100644 --- a/packages/js/data/src/plugins/actions.ts +++ b/packages/js/data/src/plugins/actions.ts @@ -13,7 +13,7 @@ import { controls } from '@wordpress/data'; /** * Internal dependencies */ -import { pluginNames, STORE_NAME } from './constants'; +import { STORE_NAME } from './constants'; import { ACTION_TYPES as TYPES } from './action-types'; import { WC_ADMIN_NAMESPACE } from '../constants'; import { WPError } from '../types'; @@ -22,6 +22,8 @@ import { PluginNames, SelectorKeysWithActions, RecommendedTypes, + InstallPluginsResponse, + ActivatePluginsResponse, } from './types'; // Can be removed in WP 5.9, wp.data is supported in >5.7. @@ -30,63 +32,12 @@ const dispatch = const resolveSelect = controls && controls.resolveSelect ? controls.resolveSelect : select; -type PluginsResponse< PluginData > = { - data: PluginData; - errors: WPError< PluginNames >; - success: boolean; - message: string; -} & Response; - -export type InstallPluginsResponse = PluginsResponse< { - installed: string[]; - results: Record< string, boolean >; - install_time?: Record< string, number >; -} >; - -type ActivatePluginsResponse = PluginsResponse< { - activated: string[]; - active: string[]; -} >; - -function isWPError( - error: WPError< PluginNames > | Error | string -): error is WPError< PluginNames > { - return ( error as WPError ).errors !== undefined; -} - class PluginError extends Error { constructor( message: string, public data: unknown ) { super( message ); } } -function formatErrors( - response: WPError< PluginNames > | Error | string -): string { - if ( isWPError( response ) ) { - // Replace the slug with a plugin name if a constant exists. - ( Object.keys( response.errors ) as PluginNames[] ).forEach( - ( plugin ) => { - response.errors[ plugin ] = response.errors[ plugin ].map( - ( pluginError ) => { - return pluginNames[ plugin ] - ? pluginError.replace( - `\`${ plugin }\``, - pluginNames[ plugin ] - ) - : pluginError; - } - ); - } - ); - } else if ( typeof response === 'string' ) { - return response; - } else { - return response.message; - } - return ''; -} - const formatErrorMessage = ( pluginErrors: Record< PluginNames, string[] >, actionType = 'install' @@ -170,6 +121,43 @@ export function updateJetpackConnectUrl( }; } +export const createErrorNotice = ( + errorMessage: string +): { + type: 'CREATE_NOTICE'; + [ key: string ]: unknown; +} => { + return dispatch( 'core/notices', 'createNotice', 'error', errorMessage ); +}; + +export function setPaypalOnboardingStatus( + status: Partial< PaypalOnboardingStatus > +): { + type: TYPES.SET_PAYPAL_ONBOARDING_STATUS; + paypalOnboardingStatus: Partial< PaypalOnboardingStatus >; +} { + return { + type: TYPES.SET_PAYPAL_ONBOARDING_STATUS as const, + paypalOnboardingStatus: status, + }; +} + +export function setRecommendedPlugins( + type: string, + plugins: Plugin[] +): { + type: TYPES.SET_RECOMMENDED_PLUGINS; + recommendedType: string; + plugins: Plugin[]; +} { + return { + type: TYPES.SET_RECOMMENDED_PLUGINS as const, + recommendedType: type, + plugins, + }; +} + +// Action Creator Generators export function* installPlugins( plugins: string[] ) { yield setIsRequesting( 'installPlugins', true ); @@ -258,15 +246,6 @@ export function* installAndActivatePlugins( plugins: string[] ) { } } -export const createErrorNotice = ( - errorMessage: string -): { - type: 'CREATE_NOTICE'; - [ key: string ]: unknown; -} => { - return dispatch( 'core/notices', 'createNotice', 'error', errorMessage ); -}; - export function* connectToJetpack( getAdminLink: ( endpoint: string ) => string ) { @@ -335,33 +314,6 @@ export function* connectToJetpackWithFailureRedirect( } } -export function setPaypalOnboardingStatus( - status: Partial< PaypalOnboardingStatus > -): { - type: TYPES.SET_PAYPAL_ONBOARDING_STATUS; - paypalOnboardingStatus: Partial< PaypalOnboardingStatus >; -} { - return { - type: TYPES.SET_PAYPAL_ONBOARDING_STATUS as const, - paypalOnboardingStatus: status, - }; -} - -export function setRecommendedPlugins( - type: string, - plugins: Plugin[] -): { - type: TYPES.SET_RECOMMENDED_PLUGINS; - recommendedType: string; - plugins: Plugin[]; -} { - return { - type: TYPES.SET_RECOMMENDED_PLUGINS as const, - recommendedType: type, - plugins, - }; -} - const SUPPORTED_TYPES = [ 'payments' ]; export function* dismissRecommendedPlugins( type: RecommendedTypes ) { if ( ! SUPPORTED_TYPES.includes( type ) ) { diff --git a/packages/js/data/src/plugins/types.ts b/packages/js/data/src/plugins/types.ts index c1f62fb7afd..85156491306 100644 --- a/packages/js/data/src/plugins/types.ts +++ b/packages/js/data/src/plugins/types.ts @@ -2,6 +2,7 @@ * Internal dependencies */ import { pluginNames } from './constants'; +import { WPError } from '../types'; export type RecommendedTypes = 'payments'; @@ -61,3 +62,21 @@ export type PaypalOnboardingStatus = { onboarded: boolean; }; }; + +type PluginsResponse< PluginData > = { + data: PluginData; + errors: WPError< PluginNames >; + success: boolean; + message: string; +} & Response; + +export type InstallPluginsResponse = PluginsResponse< { + installed: string[]; + results: Record< string, boolean >; + install_time?: Record< string, number >; +} >; + +export type ActivatePluginsResponse = PluginsResponse< { + activated: string[]; + active: string[]; +} >;