Merge pull request #33155 from woocommerce/dev/migrate-woo-data-import-export-store-to-ts
Migrate `@woocommerce/data` import & export stores to TS
This commit is contained in:
commit
785466fdd2
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: dev
|
||||
|
||||
Migrate woo.data export & import store to TS
|
|
@ -48,6 +48,7 @@
|
|||
"@babel/runtime": "^7.17.2",
|
||||
"@testing-library/react": "^12.1.3",
|
||||
"@testing-library/react-hooks": "^7.0.2",
|
||||
"@types/md5": "^2.3.2",
|
||||
"@types/wordpress__compose": "^4.0.1",
|
||||
"@types/wordpress__core-data": "^2.4.5",
|
||||
"@types/wordpress__data": "^6.0.0",
|
||||
|
|
|
@ -2,20 +2,26 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { controls as dataControls } from '@wordpress/data-controls';
|
||||
import { Action } from '@wordpress/data';
|
||||
import apiFetch, { APIFetchOptions } from '@wordpress/api-fetch';
|
||||
|
||||
import apiFetch from '@wordpress/api-fetch';
|
||||
|
||||
export const fetchWithHeaders = ( options ) => {
|
||||
export const fetchWithHeaders = ( options: APIFetchOptions ) => {
|
||||
return {
|
||||
type: 'FETCH_WITH_HEADERS',
|
||||
options,
|
||||
};
|
||||
};
|
||||
|
||||
export type FetchWithHeadersResponse< Data > = {
|
||||
headers: Response[ 'headers' ];
|
||||
status: Response[ 'status' ];
|
||||
data: Data;
|
||||
};
|
||||
|
||||
const controls = {
|
||||
...dataControls,
|
||||
FETCH_WITH_HEADERS( { options } ) {
|
||||
return apiFetch( { ...options, parse: false } )
|
||||
FETCH_WITH_HEADERS( action: Action ) {
|
||||
return apiFetch< Response >( { ...action.options, parse: false } )
|
||||
.then( ( response ) => {
|
||||
return Promise.all( [
|
||||
response.headers,
|
|
@ -1,8 +0,0 @@
|
|||
const TYPES = {
|
||||
START_EXPORT: 'START_EXPORT',
|
||||
SET_EXPORT_ID: 'SET_EXPORT_ID',
|
||||
SET_ERROR: 'SET_ERROR',
|
||||
SET_IS_REQUESTING: 'SET_IS_REQUESTING',
|
||||
};
|
||||
|
||||
export default TYPES;
|
|
@ -0,0 +1,8 @@
|
|||
const TYPES = {
|
||||
START_EXPORT: 'START_EXPORT' as const,
|
||||
SET_EXPORT_ID: 'SET_EXPORT_ID' as const,
|
||||
SET_ERROR: 'SET_ERROR' as const,
|
||||
SET_IS_REQUESTING: 'SET_IS_REQUESTING' as const,
|
||||
};
|
||||
|
||||
export default TYPES;
|
|
@ -1,64 +0,0 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { fetchWithHeaders } from '../controls';
|
||||
import TYPES from './action-types';
|
||||
import { NAMESPACE } from '../constants';
|
||||
|
||||
export function setExportId( exportType, exportArgs, exportId ) {
|
||||
return {
|
||||
type: TYPES.SET_EXPORT_ID,
|
||||
exportType,
|
||||
exportArgs,
|
||||
exportId,
|
||||
};
|
||||
}
|
||||
|
||||
export function setIsRequesting( selector, selectorArgs, isRequesting ) {
|
||||
return {
|
||||
type: TYPES.SET_IS_REQUESTING,
|
||||
selector,
|
||||
selectorArgs,
|
||||
isRequesting,
|
||||
};
|
||||
}
|
||||
|
||||
export function setError( selector, selectorArgs, error ) {
|
||||
return {
|
||||
type: TYPES.SET_ERROR,
|
||||
selector,
|
||||
selectorArgs,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export function* startExport( type, args ) {
|
||||
yield setIsRequesting( 'startExport', { type, args }, true );
|
||||
|
||||
try {
|
||||
const response = yield fetchWithHeaders( {
|
||||
path: `${ NAMESPACE }/reports/${ type }/export`,
|
||||
method: 'POST',
|
||||
data: {
|
||||
report_args: args,
|
||||
email: true,
|
||||
},
|
||||
} );
|
||||
|
||||
yield setIsRequesting( 'startExport', { type, args }, false );
|
||||
|
||||
const { export_id: exportId, message } = response.data;
|
||||
|
||||
if ( exportId ) {
|
||||
yield setExportId( type, args, exportId );
|
||||
} else {
|
||||
throw new Error( message );
|
||||
}
|
||||
|
||||
return response.data;
|
||||
} catch ( error ) {
|
||||
yield setError( 'startExport', { type, args }, error.message );
|
||||
yield setIsRequesting( 'startExport', { type, args }, false );
|
||||
throw error;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { fetchWithHeaders, FetchWithHeadersResponse } from '../controls';
|
||||
import TYPES from './action-types';
|
||||
import { NAMESPACE } from '../constants';
|
||||
import { SelectorArgs, ExportArgs } from './types';
|
||||
|
||||
export function setExportId(
|
||||
exportType: string,
|
||||
exportArgs: ExportArgs,
|
||||
exportId: string
|
||||
) {
|
||||
return {
|
||||
type: TYPES.SET_EXPORT_ID,
|
||||
exportType,
|
||||
exportArgs,
|
||||
exportId,
|
||||
};
|
||||
}
|
||||
|
||||
export function setIsRequesting(
|
||||
selector: string,
|
||||
selectorArgs: SelectorArgs,
|
||||
isRequesting: boolean
|
||||
) {
|
||||
return {
|
||||
type: TYPES.SET_IS_REQUESTING,
|
||||
selector,
|
||||
selectorArgs,
|
||||
isRequesting,
|
||||
};
|
||||
}
|
||||
|
||||
export function setError(
|
||||
selector: string,
|
||||
selectorArgs: SelectorArgs,
|
||||
error: unknown
|
||||
) {
|
||||
return {
|
||||
type: TYPES.SET_ERROR,
|
||||
selector,
|
||||
selectorArgs,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export function* startExport( type: string, args: ExportArgs ) {
|
||||
yield setIsRequesting( 'startExport', { type, args }, true );
|
||||
|
||||
try {
|
||||
const response: FetchWithHeadersResponse< {
|
||||
export_id: string;
|
||||
message: string;
|
||||
} > = yield fetchWithHeaders( {
|
||||
path: `${ NAMESPACE }/reports/${ type }/export`,
|
||||
method: 'POST',
|
||||
data: {
|
||||
report_args: args,
|
||||
email: true,
|
||||
},
|
||||
} );
|
||||
|
||||
yield setIsRequesting( 'startExport', { type, args }, false );
|
||||
const { export_id: exportId, message } = response.data;
|
||||
|
||||
if ( exportId ) {
|
||||
yield setExportId( type, args, exportId );
|
||||
} else {
|
||||
throw new Error( message );
|
||||
}
|
||||
|
||||
return response.data;
|
||||
} catch ( error ) {
|
||||
if ( error instanceof Error ) {
|
||||
yield setError( 'startExport', { type, args }, error.message );
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error( `Unexpected Error: ${ JSON.stringify( error ) }` );
|
||||
// eslint-enable-next-line no-console
|
||||
}
|
||||
yield setIsRequesting( 'startExport', { type, args }, false );
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export type Action = ReturnType<
|
||||
typeof setExportId | typeof setError | typeof setIsRequesting
|
||||
>;
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
export const STORE_NAME = 'wc/admin/export';
|
||||
export const STORE_NAME = 'wc/admin/export' as const;
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
/**
|
||||
* 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 controls from '../controls';
|
||||
import reducer from './reducer';
|
||||
|
||||
registerStore( STORE_NAME, {
|
||||
reducer,
|
||||
actions,
|
||||
controls,
|
||||
selectors,
|
||||
} );
|
||||
|
||||
export const EXPORT_STORE_NAME = STORE_NAME;
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerStore } from '@wordpress/data';
|
||||
import { controls } from '@wordpress/data-controls';
|
||||
import { SelectFromMap, DispatchFromMap } from '@automattic/data-stores';
|
||||
import { Reducer, AnyAction } from 'redux';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { STORE_NAME } from './constants';
|
||||
import * as selectors from './selectors';
|
||||
import * as actions from './actions';
|
||||
import reducer, { State } from './reducer';
|
||||
import { WPDataSelectors } from '../types';
|
||||
export * from './types';
|
||||
export type { State };
|
||||
|
||||
registerStore< State >( STORE_NAME, {
|
||||
reducer: reducer as Reducer< State, AnyAction >,
|
||||
actions,
|
||||
controls,
|
||||
selectors,
|
||||
} );
|
||||
|
||||
export const EXPORT_STORE_NAME = STORE_NAME;
|
||||
|
||||
declare module '@wordpress/data' {
|
||||
// TODO: convert action.js to TS
|
||||
function dispatch(
|
||||
key: typeof STORE_NAME
|
||||
): DispatchFromMap< typeof actions >;
|
||||
function select(
|
||||
key: typeof STORE_NAME
|
||||
): SelectFromMap< typeof selectors > & WPDataSelectors;
|
||||
}
|
|
@ -1,40 +1,42 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
|
||||
import type { Reducer } from 'redux';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import TYPES from './action-types';
|
||||
import { Action } from './actions';
|
||||
import { hashExportArgs } from './utils';
|
||||
import { ExportState } from './types';
|
||||
|
||||
const exportReducer = (
|
||||
const reducer: Reducer< ExportState, Action > = (
|
||||
state = {
|
||||
errors: {},
|
||||
requesting: {},
|
||||
exportMeta: {},
|
||||
exportIds: {},
|
||||
},
|
||||
{
|
||||
error,
|
||||
exportArgs,
|
||||
exportId,
|
||||
exportType,
|
||||
isRequesting,
|
||||
selector,
|
||||
selectorArgs,
|
||||
type,
|
||||
}
|
||||
action
|
||||
) => {
|
||||
switch ( type ) {
|
||||
switch ( action.type ) {
|
||||
case TYPES.SET_IS_REQUESTING:
|
||||
return {
|
||||
...state,
|
||||
requesting: {
|
||||
...state.requesting,
|
||||
[ selector ]: {
|
||||
...state.requesting[ selector ],
|
||||
[ hashExportArgs( selectorArgs ) ]: isRequesting,
|
||||
[ action.selector ]: {
|
||||
...state.requesting[ action.selector ],
|
||||
[ hashExportArgs(
|
||||
action.selectorArgs
|
||||
) ]: action.isRequesting,
|
||||
},
|
||||
},
|
||||
};
|
||||
case TYPES.SET_EXPORT_ID:
|
||||
const { exportType, exportArgs, exportId } = action;
|
||||
return {
|
||||
...state,
|
||||
exportMeta: {
|
||||
|
@ -60,9 +62,9 @@ const exportReducer = (
|
|||
...state,
|
||||
errors: {
|
||||
...state.errors,
|
||||
[ selector ]: {
|
||||
...state.errors[ selector ],
|
||||
[ hashExportArgs( selectorArgs ) ]: error,
|
||||
[ action.selector ]: {
|
||||
...state.errors[ action.selector ],
|
||||
[ hashExportArgs( action.selectorArgs ) ]: action.error,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -71,4 +73,5 @@ const exportReducer = (
|
|||
}
|
||||
};
|
||||
|
||||
export default exportReducer;
|
||||
export type State = ReturnType< typeof reducer >;
|
||||
export default reducer;
|
|
@ -2,22 +2,35 @@
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { hashExportArgs } from './utils';
|
||||
import { ExportState, SelectorArgs, ExportArgs } from './types';
|
||||
|
||||
export const isExportRequesting = ( state, selector, selectorArgs ) => {
|
||||
export const isExportRequesting = (
|
||||
state: ExportState,
|
||||
selector: string,
|
||||
selectorArgs: SelectorArgs
|
||||
) => {
|
||||
return Boolean(
|
||||
state.requesting[ selector ] &&
|
||||
state.requesting[ selector ][ hashExportArgs( selectorArgs ) ]
|
||||
);
|
||||
};
|
||||
|
||||
export const getExportId = ( state, exportType, exportArgs ) => {
|
||||
export const getExportId = (
|
||||
state: ExportState,
|
||||
exportType: string,
|
||||
exportArgs: ExportArgs
|
||||
) => {
|
||||
return (
|
||||
state.exportIds[ exportType ] &&
|
||||
state.exportIds[ exportType ][ hashExportArgs( exportArgs ) ]
|
||||
);
|
||||
};
|
||||
|
||||
export const getError = ( state, selector, selectorArgs ) => {
|
||||
export const getError = (
|
||||
state: ExportState,
|
||||
selector: string,
|
||||
selectorArgs: SelectorArgs
|
||||
) => {
|
||||
return (
|
||||
state.errors[ selector ] &&
|
||||
state.errors[ selector ][ hashExportArgs( selectorArgs ) ]
|
|
@ -18,6 +18,7 @@ const defaultState = {
|
|||
|
||||
describe( 'export reducer', () => {
|
||||
it( 'should return a default state', () => {
|
||||
// @ts-expect-error reducer action should not be empty but it is
|
||||
const state = reducer( undefined, {} );
|
||||
expect( state ).toEqual( defaultState );
|
||||
expect( state ).not.toBe( defaultState );
|
|
@ -0,0 +1,32 @@
|
|||
export type ExportArgs = {
|
||||
[ key: string ]: unknown;
|
||||
};
|
||||
|
||||
export type SelectorArgs = {
|
||||
type: string;
|
||||
args: ExportArgs;
|
||||
};
|
||||
|
||||
export type ExportState = {
|
||||
errors: {
|
||||
[ selector: string ]: {
|
||||
[ hashExportArgs: string ]: unknown;
|
||||
};
|
||||
};
|
||||
requesting: {
|
||||
[ selector: string ]: {
|
||||
[ hashExportArgs: string ]: boolean;
|
||||
};
|
||||
};
|
||||
exportMeta: {
|
||||
[ exportId: string ]: {
|
||||
exportType: string;
|
||||
exportArgs: ExportArgs;
|
||||
};
|
||||
};
|
||||
exportIds: {
|
||||
[ exportType: string ]: {
|
||||
[ hashExportArgs: string ]: string;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -7,7 +7,8 @@ import md5 from 'md5';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { getResourceName } from '../utils';
|
||||
import { ExportArgs } from './types';
|
||||
|
||||
export const hashExportArgs = ( args ) => {
|
||||
export const hashExportArgs = ( args: ExportArgs ) => {
|
||||
return md5( getResourceName( 'export', args ) );
|
||||
};
|
|
@ -1,11 +0,0 @@
|
|||
const TYPES = {
|
||||
SET_IMPORT_DATE: 'SET_IMPORT_DATE',
|
||||
SET_IMPORT_ERROR: 'SET_IMPORT_ERROR',
|
||||
SET_IMPORT_PERIOD: 'SET_IMPORT_PERIOD',
|
||||
SET_IMPORT_STARTED: 'SET_IMPORT_STARTED',
|
||||
SET_IMPORT_STATUS: 'SET_IMPORT_STATUS',
|
||||
SET_IMPORT_TOTALS: 'SET_IMPORT_TOTALS',
|
||||
SET_SKIP_IMPORTED: 'SET_SKIP_IMPORTED',
|
||||
};
|
||||
|
||||
export default TYPES;
|
|
@ -0,0 +1,11 @@
|
|||
const TYPES = {
|
||||
SET_IMPORT_DATE: 'SET_IMPORT_DATE' as const,
|
||||
SET_IMPORT_ERROR: 'SET_IMPORT_ERROR' as const,
|
||||
SET_IMPORT_PERIOD: 'SET_IMPORT_PERIOD' as const,
|
||||
SET_IMPORT_STARTED: 'SET_IMPORT_STARTED' as const,
|
||||
SET_IMPORT_STATUS: 'SET_IMPORT_STATUS' as const,
|
||||
SET_IMPORT_TOTALS: 'SET_IMPORT_TOTALS' as const,
|
||||
SET_SKIP_IMPORTED: 'SET_SKIP_IMPORTED' as const,
|
||||
};
|
||||
|
||||
export default TYPES;
|
|
@ -1,71 +0,0 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { apiFetch } from '@wordpress/data-controls';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import TYPES from './action-types';
|
||||
|
||||
export function setImportStarted( activeImport ) {
|
||||
return {
|
||||
type: TYPES.SET_IMPORT_STARTED,
|
||||
activeImport,
|
||||
};
|
||||
}
|
||||
|
||||
export function setImportPeriod( date, dateModified ) {
|
||||
if ( ! dateModified ) {
|
||||
return {
|
||||
type: TYPES.SET_IMPORT_PERIOD,
|
||||
date,
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: TYPES.SET_IMPORT_DATE,
|
||||
date,
|
||||
};
|
||||
}
|
||||
|
||||
export function setSkipPrevious( skipPrevious ) {
|
||||
return {
|
||||
type: TYPES.SET_SKIP_IMPORTED,
|
||||
skipPrevious,
|
||||
};
|
||||
}
|
||||
|
||||
export function setImportStatus( query, importStatus ) {
|
||||
return {
|
||||
type: TYPES.SET_IMPORT_STATUS,
|
||||
importStatus,
|
||||
query,
|
||||
};
|
||||
}
|
||||
|
||||
export function setImportTotals( query, importTotals ) {
|
||||
return {
|
||||
type: TYPES.SET_IMPORT_TOTALS,
|
||||
importTotals,
|
||||
query,
|
||||
};
|
||||
}
|
||||
|
||||
export function setImportError( query, error ) {
|
||||
return {
|
||||
type: TYPES.SET_IMPORT_ERROR,
|
||||
error,
|
||||
query,
|
||||
};
|
||||
}
|
||||
|
||||
export function* updateImportation( path, importStarted = false ) {
|
||||
yield setImportStarted( importStarted );
|
||||
try {
|
||||
const response = yield apiFetch( { path, method: 'POST' } );
|
||||
return response;
|
||||
} catch ( error ) {
|
||||
yield setImportError( path, error );
|
||||
throw error;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { apiFetch } from '@wordpress/data-controls';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import TYPES from './action-types';
|
||||
import {
|
||||
ImportStatusQuery,
|
||||
ImportStatus,
|
||||
ImportTotals,
|
||||
ImportTotalsQuery,
|
||||
} from './types';
|
||||
|
||||
export function setImportStarted( activeImport: boolean ) {
|
||||
return {
|
||||
type: TYPES.SET_IMPORT_STARTED,
|
||||
activeImport,
|
||||
};
|
||||
}
|
||||
|
||||
export function setImportPeriod( date: string, dateModified: boolean ) {
|
||||
if ( ! dateModified ) {
|
||||
return {
|
||||
type: TYPES.SET_IMPORT_PERIOD,
|
||||
date,
|
||||
};
|
||||
}
|
||||
return {
|
||||
type: TYPES.SET_IMPORT_DATE,
|
||||
date,
|
||||
};
|
||||
}
|
||||
|
||||
export function setSkipPrevious( skipPrevious: boolean ) {
|
||||
return {
|
||||
type: TYPES.SET_SKIP_IMPORTED,
|
||||
skipPrevious,
|
||||
};
|
||||
}
|
||||
|
||||
export function setImportStatus(
|
||||
query: ImportStatusQuery,
|
||||
importStatus: ImportStatus
|
||||
) {
|
||||
return {
|
||||
type: TYPES.SET_IMPORT_STATUS,
|
||||
importStatus,
|
||||
query,
|
||||
};
|
||||
}
|
||||
|
||||
export function setImportTotals(
|
||||
query: ImportTotalsQuery,
|
||||
importTotals: ImportTotals
|
||||
) {
|
||||
return {
|
||||
type: TYPES.SET_IMPORT_TOTALS,
|
||||
importTotals,
|
||||
query,
|
||||
};
|
||||
}
|
||||
|
||||
export function setImportError(
|
||||
queryOrPath: ImportStatusQuery | ImportTotalsQuery | string,
|
||||
error: unknown
|
||||
) {
|
||||
return {
|
||||
type: TYPES.SET_IMPORT_ERROR,
|
||||
error,
|
||||
query: queryOrPath,
|
||||
};
|
||||
}
|
||||
|
||||
export function* updateImportation( path: string, importStarted = false ) {
|
||||
yield setImportStarted( importStarted );
|
||||
try {
|
||||
const response: unknown = yield apiFetch( { path, method: 'POST' } );
|
||||
return response;
|
||||
} catch ( error ) {
|
||||
yield setImportError( path, error );
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export type Action = ReturnType<
|
||||
| typeof setImportStarted
|
||||
| typeof setImportPeriod
|
||||
| typeof setImportStatus
|
||||
| typeof setImportTotals
|
||||
| typeof setImportError
|
||||
| typeof setSkipPrevious
|
||||
>;
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
export const STORE_NAME = 'wc/admin/import';
|
||||
export const STORE_NAME = 'wc/admin/import' 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 IMPORT_STORE_NAME = STORE_NAME;
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerStore } from '@wordpress/data';
|
||||
import { controls } from '@wordpress/data-controls';
|
||||
import { SelectFromMap, DispatchFromMap } from '@automattic/data-stores';
|
||||
import { Reducer, AnyAction } from 'redux';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { STORE_NAME } from './constants';
|
||||
import * as selectors from './selectors';
|
||||
import * as actions from './actions';
|
||||
import reducer, { State } from './reducer';
|
||||
import { WPDataSelectors } from '../types';
|
||||
export * from './types';
|
||||
export type { State };
|
||||
|
||||
registerStore< State >( STORE_NAME, {
|
||||
reducer: reducer as Reducer< State, AnyAction >,
|
||||
actions,
|
||||
controls,
|
||||
selectors,
|
||||
} );
|
||||
|
||||
export const IMPORT_STORE_NAME = STORE_NAME;
|
||||
|
||||
declare module '@wordpress/data' {
|
||||
// TODO: convert action.js to TS
|
||||
function dispatch(
|
||||
key: typeof STORE_NAME
|
||||
): DispatchFromMap< typeof actions >;
|
||||
function select(
|
||||
key: typeof STORE_NAME
|
||||
): SelectFromMap< typeof selectors > & WPDataSelectors;
|
||||
}
|
|
@ -3,13 +3,16 @@
|
|||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import moment from 'moment';
|
||||
import type { Reducer } from 'redux';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import TYPES from './action-types';
|
||||
import { ImportState } from './types';
|
||||
import { Action } from './actions';
|
||||
|
||||
const reducer = (
|
||||
const reducer: Reducer< ImportState, Action > = (
|
||||
state = {
|
||||
activeImport: false,
|
||||
importStatus: {},
|
||||
|
@ -22,19 +25,11 @@ const reducer = (
|
|||
},
|
||||
skipPrevious: true,
|
||||
},
|
||||
{
|
||||
type,
|
||||
query,
|
||||
importStatus,
|
||||
importTotals,
|
||||
activeImport,
|
||||
date,
|
||||
error,
|
||||
skipPrevious,
|
||||
}
|
||||
action
|
||||
) => {
|
||||
switch ( type ) {
|
||||
switch ( action.type ) {
|
||||
case TYPES.SET_IMPORT_STARTED:
|
||||
const { activeImport } = action;
|
||||
state = {
|
||||
...state,
|
||||
activeImport,
|
||||
|
@ -48,7 +43,7 @@ const reducer = (
|
|||
...state,
|
||||
period: {
|
||||
...state.period,
|
||||
label: date,
|
||||
label: action.date,
|
||||
},
|
||||
activeImport: false,
|
||||
};
|
||||
|
@ -57,7 +52,7 @@ const reducer = (
|
|||
state = {
|
||||
...state,
|
||||
period: {
|
||||
date,
|
||||
date: action.date,
|
||||
label: 'custom',
|
||||
},
|
||||
activeImport: false,
|
||||
|
@ -66,11 +61,12 @@ const reducer = (
|
|||
case TYPES.SET_SKIP_IMPORTED:
|
||||
state = {
|
||||
...state,
|
||||
skipPrevious,
|
||||
skipPrevious: action.skipPrevious,
|
||||
activeImport: false,
|
||||
};
|
||||
break;
|
||||
case TYPES.SET_IMPORT_STATUS:
|
||||
const { query, importStatus } = action;
|
||||
state = {
|
||||
...state,
|
||||
importStatus: {
|
||||
|
@ -88,7 +84,7 @@ const reducer = (
|
|||
...state,
|
||||
importTotals: {
|
||||
...state.importTotals,
|
||||
[ JSON.stringify( query ) ]: importTotals,
|
||||
[ JSON.stringify( action.query ) ]: action.importTotals,
|
||||
},
|
||||
};
|
||||
break;
|
||||
|
@ -97,7 +93,7 @@ const reducer = (
|
|||
...state,
|
||||
errors: {
|
||||
...state.errors,
|
||||
[ JSON.stringify( query ) ]: error,
|
||||
[ JSON.stringify( action.query ) ]: action.error,
|
||||
},
|
||||
};
|
||||
break;
|
||||
|
@ -105,4 +101,5 @@ const reducer = (
|
|||
return state;
|
||||
};
|
||||
|
||||
export type State = ReturnType< typeof reducer >;
|
||||
export default reducer;
|
|
@ -10,27 +10,33 @@ import { omit } from 'lodash';
|
|||
*/
|
||||
import { NAMESPACE } from '../constants';
|
||||
import { setImportError, setImportStatus, setImportTotals } from './actions';
|
||||
import {
|
||||
ImportStatusQuery,
|
||||
ImportTotalsQuery,
|
||||
ImportStatus,
|
||||
ImportTotals,
|
||||
} from './types';
|
||||
|
||||
export function* getImportStatus( query ) {
|
||||
export function* getImportStatus( query: ImportStatusQuery ) {
|
||||
try {
|
||||
const url = addQueryArgs(
|
||||
`${ NAMESPACE }/reports/import/status`,
|
||||
omit( query, [ 'timestamp' ] )
|
||||
typeof query === 'object' ? omit( query, [ 'timestamp' ] ) : {}
|
||||
);
|
||||
const response = yield apiFetch( { path: url } );
|
||||
const response: ImportStatus = yield apiFetch( { path: url } );
|
||||
yield setImportStatus( query, response );
|
||||
} catch ( error ) {
|
||||
yield setImportError( query, error );
|
||||
}
|
||||
}
|
||||
|
||||
export function* getImportTotals( query ) {
|
||||
export function* getImportTotals( query: ImportTotalsQuery ) {
|
||||
try {
|
||||
const url = addQueryArgs(
|
||||
`${ NAMESPACE }/reports/import/totals`,
|
||||
query
|
||||
);
|
||||
const response = yield apiFetch( { path: url } );
|
||||
const response: ImportTotals = yield apiFetch( { path: url } );
|
||||
yield setImportTotals( query, response );
|
||||
} catch ( error ) {
|
||||
yield setImportError( query, error );
|
|
@ -1,19 +1,31 @@
|
|||
export const getImportStarted = ( state ) => {
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
|
||||
import { ImportState, ImportStatusQuery, ImportTotalsQuery } from './types';
|
||||
|
||||
export const getImportStarted = ( state: ImportState ) => {
|
||||
const { activeImport, lastImportStartTimestamp } = state;
|
||||
return { activeImport, lastImportStartTimestamp } || {};
|
||||
};
|
||||
|
||||
export const getFormSettings = ( state ) => {
|
||||
export const getFormSettings = ( state: ImportState ) => {
|
||||
const { period, skipPrevious } = state;
|
||||
return { period, skipPrevious } || {};
|
||||
};
|
||||
|
||||
export const getImportStatus = ( state, query ) => {
|
||||
export const getImportStatus = (
|
||||
state: ImportState,
|
||||
query: ImportStatusQuery
|
||||
) => {
|
||||
const stringifiedQuery = JSON.stringify( query );
|
||||
return state.importStatus[ stringifiedQuery ] || {};
|
||||
};
|
||||
|
||||
export const getImportTotals = ( state, query ) => {
|
||||
export const getImportTotals = (
|
||||
state: ImportState,
|
||||
query: ImportTotalsQuery
|
||||
) => {
|
||||
const { importTotals, lastImportStartTimestamp } = state;
|
||||
const stringifiedQuery = JSON.stringify( query );
|
||||
return (
|
||||
|
@ -24,7 +36,10 @@ export const getImportTotals = ( state, query ) => {
|
|||
);
|
||||
};
|
||||
|
||||
export const getImportError = ( state, query ) => {
|
||||
export const getImportError = (
|
||||
state: ImportState,
|
||||
query: ImportTotalsQuery | ImportStatusQuery | string
|
||||
) => {
|
||||
const stringifiedQuery = JSON.stringify( query );
|
||||
return state.errors[ stringifiedQuery ] || false;
|
||||
};
|
|
@ -24,6 +24,7 @@ const defaultState = {
|
|||
|
||||
describe( 'import reducer', () => {
|
||||
it( 'should return a default state', () => {
|
||||
// @ts-expect-error reducer action should not be empty but it is
|
||||
const state = reducer( undefined, {} );
|
||||
expect( state ).toEqual( defaultState );
|
||||
expect( state ).not.toBe( defaultState );
|
||||
|
@ -113,7 +114,10 @@ describe( 'import reducer', () => {
|
|||
error: { code: 'error' },
|
||||
} );
|
||||
const stringifiedQuery = JSON.stringify( query );
|
||||
|
||||
expect( state.errors[ stringifiedQuery ].code ).toBe( 'error' );
|
||||
expect(
|
||||
( state.errors[ stringifiedQuery ] as {
|
||||
code: string;
|
||||
} ).code
|
||||
).toBe( 'error' );
|
||||
} );
|
||||
} );
|
|
@ -0,0 +1,52 @@
|
|||
type SchedulerName = 'orders' | 'customers';
|
||||
|
||||
type isImporting = {
|
||||
is_importing: boolean;
|
||||
};
|
||||
|
||||
type SchedulerImportStatus = {
|
||||
[ schedulerName in SchedulerName ]: {
|
||||
imported: number;
|
||||
totals: number;
|
||||
};
|
||||
} & {
|
||||
imported_from?: string | number;
|
||||
};
|
||||
|
||||
export type ImportStatus =
|
||||
| isImporting
|
||||
| ( isImporting & SchedulerImportStatus );
|
||||
|
||||
export type ImportStatusQuery = number;
|
||||
|
||||
export type ImportTotals = {
|
||||
[ schedulerName in SchedulerName ]: number;
|
||||
};
|
||||
|
||||
export type ImportTotalsQuery = {
|
||||
skip_existing: boolean;
|
||||
days: number;
|
||||
};
|
||||
|
||||
export type ImportState = {
|
||||
activeImport: boolean;
|
||||
importStatus:
|
||||
| Record< string, never >
|
||||
| {
|
||||
[ queryString: string ]: ImportStatus;
|
||||
};
|
||||
importTotals:
|
||||
| Record< string, never >
|
||||
| {
|
||||
[ queryString: string ]: ImportTotals;
|
||||
};
|
||||
errors: {
|
||||
[ queryString: string ]: unknown;
|
||||
};
|
||||
lastImportStartTimestamp: number;
|
||||
period: {
|
||||
date: string;
|
||||
label: string;
|
||||
};
|
||||
skipPrevious: boolean;
|
||||
};
|
|
@ -485,6 +485,7 @@ importers:
|
|||
'@babel/runtime': ^7.17.2
|
||||
'@testing-library/react': ^12.1.3
|
||||
'@testing-library/react-hooks': ^7.0.2
|
||||
'@types/md5': ^2.3.2
|
||||
'@types/wordpress__compose': ^4.0.1
|
||||
'@types/wordpress__core-data': ^2.4.5
|
||||
'@types/wordpress__data': ^6.0.0
|
||||
|
@ -536,6 +537,7 @@ importers:
|
|||
'@babel/runtime': 7.17.7
|
||||
'@testing-library/react': 12.1.4
|
||||
'@testing-library/react-hooks': 7.0.2
|
||||
'@types/md5': 2.3.2
|
||||
'@types/wordpress__compose': 4.0.1
|
||||
'@types/wordpress__core-data': 2.4.5
|
||||
'@types/wordpress__data': 6.0.0
|
||||
|
@ -13428,6 +13430,10 @@ packages:
|
|||
/@types/lodash/4.14.180:
|
||||
resolution: {integrity: sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g==}
|
||||
|
||||
/@types/md5/2.3.2:
|
||||
resolution: {integrity: sha512-v+JFDu96+UYJ3/UWzB0mEglIS//MZXgRaJ4ubUPwOM0gvLc/kcQ3TWNYwENEK7/EcXGQVrW8h/XqednSjBd/Og==}
|
||||
dev: true
|
||||
|
||||
/@types/mdast/3.0.10:
|
||||
resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==}
|
||||
dependencies:
|
||||
|
@ -39232,7 +39238,7 @@ packages:
|
|||
tapable: 1.1.3
|
||||
terser-webpack-plugin: 1.4.5_webpack@4.46.0
|
||||
watchpack: 1.7.5
|
||||
webpack-cli: 3.3.12_webpack@5.70.0
|
||||
webpack-cli: 3.3.12_webpack@4.46.0
|
||||
webpack-sources: 1.4.3
|
||||
dev: true
|
||||
|
||||
|
|
Loading…
Reference in New Issue