Migrate woo.data export & import store to TS
This commit is contained in:
parent
19a3e2c892
commit
b8d79d86cf
|
@ -48,6 +48,7 @@
|
||||||
"@babel/runtime": "^7.17.2",
|
"@babel/runtime": "^7.17.2",
|
||||||
"@testing-library/react": "^12.1.3",
|
"@testing-library/react": "^12.1.3",
|
||||||
"@testing-library/react-hooks": "^7.0.2",
|
"@testing-library/react-hooks": "^7.0.2",
|
||||||
|
"@types/md5": "^2.3.2",
|
||||||
"@types/wordpress__compose": "^4.0.1",
|
"@types/wordpress__compose": "^4.0.1",
|
||||||
"@types/wordpress__core-data": "^2.4.5",
|
"@types/wordpress__core-data": "^2.4.5",
|
||||||
"@types/wordpress__data": "^6.0.0",
|
"@types/wordpress__data": "^6.0.0",
|
||||||
|
|
|
@ -2,20 +2,26 @@
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { controls as dataControls } from '@wordpress/data-controls';
|
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: APIFetchOptions ) => {
|
||||||
|
|
||||||
export const fetchWithHeaders = ( options ) => {
|
|
||||||
return {
|
return {
|
||||||
type: 'FETCH_WITH_HEADERS',
|
type: 'FETCH_WITH_HEADERS',
|
||||||
options,
|
options,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type FetchWithHeadersResponse< Data > = {
|
||||||
|
headers: Response[ 'headers' ];
|
||||||
|
status: Response[ 'status' ];
|
||||||
|
data: Data;
|
||||||
|
};
|
||||||
|
|
||||||
const controls = {
|
const controls = {
|
||||||
...dataControls,
|
...dataControls,
|
||||||
FETCH_WITH_HEADERS( { options } ) {
|
FETCH_WITH_HEADERS( action: Action ) {
|
||||||
return apiFetch( { ...options, parse: false } )
|
return apiFetch< Response >( { ...action.options, parse: false } )
|
||||||
.then( ( response ) => {
|
.then( ( response ) => {
|
||||||
return Promise.all( [
|
return Promise.all( [
|
||||||
response.headers,
|
response.headers,
|
|
@ -1,8 +1,8 @@
|
||||||
const TYPES = {
|
const TYPES = {
|
||||||
START_EXPORT: 'START_EXPORT',
|
START_EXPORT: 'START_EXPORT' as const,
|
||||||
SET_EXPORT_ID: 'SET_EXPORT_ID',
|
SET_EXPORT_ID: 'SET_EXPORT_ID' as const,
|
||||||
SET_ERROR: 'SET_ERROR',
|
SET_ERROR: 'SET_ERROR' as const,
|
||||||
SET_IS_REQUESTING: 'SET_IS_REQUESTING',
|
SET_IS_REQUESTING: 'SET_IS_REQUESTING' as const,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TYPES;
|
export default TYPES;
|
||||||
|
|
|
@ -1,11 +1,16 @@
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { fetchWithHeaders } from '../controls';
|
import { fetchWithHeaders, FetchWithHeadersResponse } from '../controls';
|
||||||
import TYPES from './action-types';
|
import TYPES from './action-types';
|
||||||
import { NAMESPACE } from '../constants';
|
import { NAMESPACE } from '../constants';
|
||||||
|
import { SelectorArgs, ExportArgs } from './types';
|
||||||
|
|
||||||
export function setExportId( exportType, exportArgs, exportId ) {
|
export function setExportId(
|
||||||
|
exportType: string,
|
||||||
|
exportArgs: ExportArgs,
|
||||||
|
exportId: string
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
type: TYPES.SET_EXPORT_ID,
|
type: TYPES.SET_EXPORT_ID,
|
||||||
exportType,
|
exportType,
|
||||||
|
@ -14,7 +19,11 @@ export function setExportId( exportType, exportArgs, exportId ) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setIsRequesting( selector, selectorArgs, isRequesting ) {
|
export function setIsRequesting(
|
||||||
|
selector: string,
|
||||||
|
selectorArgs: SelectorArgs,
|
||||||
|
isRequesting: boolean
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
type: TYPES.SET_IS_REQUESTING,
|
type: TYPES.SET_IS_REQUESTING,
|
||||||
selector,
|
selector,
|
||||||
|
@ -23,7 +32,11 @@ export function setIsRequesting( selector, selectorArgs, isRequesting ) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setError( selector, selectorArgs, error ) {
|
export function setError(
|
||||||
|
selector: string,
|
||||||
|
selectorArgs: SelectorArgs,
|
||||||
|
error: unknown
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
type: TYPES.SET_ERROR,
|
type: TYPES.SET_ERROR,
|
||||||
selector,
|
selector,
|
||||||
|
@ -32,11 +45,14 @@ export function setError( selector, selectorArgs, error ) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* startExport( type, args ) {
|
export function* startExport( type: string, args: ExportArgs ) {
|
||||||
yield setIsRequesting( 'startExport', { type, args }, true );
|
yield setIsRequesting( 'startExport', { type, args }, true );
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = yield fetchWithHeaders( {
|
const response: FetchWithHeadersResponse< {
|
||||||
|
export_id: string;
|
||||||
|
message: string;
|
||||||
|
} > = yield fetchWithHeaders( {
|
||||||
path: `${ NAMESPACE }/reports/${ type }/export`,
|
path: `${ NAMESPACE }/reports/${ type }/export`,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: {
|
data: {
|
||||||
|
@ -46,7 +62,6 @@ export function* startExport( type, args ) {
|
||||||
} );
|
} );
|
||||||
|
|
||||||
yield setIsRequesting( 'startExport', { type, args }, false );
|
yield setIsRequesting( 'startExport', { type, args }, false );
|
||||||
|
|
||||||
const { export_id: exportId, message } = response.data;
|
const { export_id: exportId, message } = response.data;
|
||||||
|
|
||||||
if ( exportId ) {
|
if ( exportId ) {
|
||||||
|
@ -57,8 +72,18 @@ export function* startExport( type, args ) {
|
||||||
|
|
||||||
return response.data;
|
return response.data;
|
||||||
} catch ( error ) {
|
} catch ( error ) {
|
||||||
|
if ( error instanceof Error ) {
|
||||||
yield setError( 'startExport', { type, args }, error.message );
|
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 );
|
yield setIsRequesting( 'startExport', { type, args }, false );
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Action = ReturnType<
|
||||||
|
typeof setExportId | typeof setError | typeof setIsRequesting
|
||||||
|
>;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
export const STORE_NAME = 'wc/admin/export';
|
export const STORE_NAME = 'wc/admin/export' as const;
|
||||||
|
|
|
@ -1,23 +1,36 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { registerStore } from '@wordpress/data';
|
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
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { STORE_NAME } from './constants';
|
import { STORE_NAME } from './constants';
|
||||||
import * as selectors from './selectors';
|
import * as selectors from './selectors';
|
||||||
import * as actions from './actions';
|
import * as actions from './actions';
|
||||||
import controls from '../controls';
|
import reducer, { State } from './reducer';
|
||||||
import reducer from './reducer';
|
import { WPDataSelectors } from '../types';
|
||||||
|
export * from './types';
|
||||||
|
export type { State };
|
||||||
|
|
||||||
registerStore( STORE_NAME, {
|
registerStore< State >( STORE_NAME, {
|
||||||
reducer,
|
reducer: reducer as Reducer< State, AnyAction >,
|
||||||
actions,
|
actions,
|
||||||
controls,
|
controls,
|
||||||
selectors,
|
selectors,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
export const EXPORT_STORE_NAME = STORE_NAME;
|
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
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import TYPES from './action-types';
|
import TYPES from './action-types';
|
||||||
|
import { Action } from './actions';
|
||||||
import { hashExportArgs } from './utils';
|
import { hashExportArgs } from './utils';
|
||||||
|
import { ExportState } from './types';
|
||||||
|
|
||||||
const exportReducer = (
|
const reducer: Reducer< ExportState, Action > = (
|
||||||
state = {
|
state = {
|
||||||
errors: {},
|
errors: {},
|
||||||
requesting: {},
|
requesting: {},
|
||||||
exportMeta: {},
|
exportMeta: {},
|
||||||
exportIds: {},
|
exportIds: {},
|
||||||
},
|
},
|
||||||
{
|
action
|
||||||
error,
|
|
||||||
exportArgs,
|
|
||||||
exportId,
|
|
||||||
exportType,
|
|
||||||
isRequesting,
|
|
||||||
selector,
|
|
||||||
selectorArgs,
|
|
||||||
type,
|
|
||||||
}
|
|
||||||
) => {
|
) => {
|
||||||
switch ( type ) {
|
switch ( action.type ) {
|
||||||
case TYPES.SET_IS_REQUESTING:
|
case TYPES.SET_IS_REQUESTING:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
requesting: {
|
requesting: {
|
||||||
...state.requesting,
|
...state.requesting,
|
||||||
[ selector ]: {
|
[ action.selector ]: {
|
||||||
...state.requesting[ selector ],
|
...state.requesting[ action.selector ],
|
||||||
[ hashExportArgs( selectorArgs ) ]: isRequesting,
|
[ hashExportArgs(
|
||||||
|
action.selectorArgs
|
||||||
|
) ]: action.isRequesting,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
case TYPES.SET_EXPORT_ID:
|
case TYPES.SET_EXPORT_ID:
|
||||||
|
const { exportType, exportArgs, exportId } = action;
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
exportMeta: {
|
exportMeta: {
|
||||||
|
@ -60,9 +62,9 @@ const exportReducer = (
|
||||||
...state,
|
...state,
|
||||||
errors: {
|
errors: {
|
||||||
...state.errors,
|
...state.errors,
|
||||||
[ selector ]: {
|
[ action.selector ]: {
|
||||||
...state.errors[ selector ],
|
...state.errors[ action.selector ],
|
||||||
[ hashExportArgs( selectorArgs ) ]: error,
|
[ 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
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { hashExportArgs } from './utils';
|
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(
|
return Boolean(
|
||||||
state.requesting[ selector ] &&
|
state.requesting[ selector ] &&
|
||||||
state.requesting[ selector ][ hashExportArgs( selectorArgs ) ]
|
state.requesting[ selector ][ hashExportArgs( selectorArgs ) ]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getExportId = ( state, exportType, exportArgs ) => {
|
export const getExportId = (
|
||||||
|
state: ExportState,
|
||||||
|
exportType: string,
|
||||||
|
exportArgs: ExportArgs
|
||||||
|
) => {
|
||||||
return (
|
return (
|
||||||
state.exportIds[ exportType ] &&
|
state.exportIds[ exportType ] &&
|
||||||
state.exportIds[ exportType ][ hashExportArgs( exportArgs ) ]
|
state.exportIds[ exportType ][ hashExportArgs( exportArgs ) ]
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getError = ( state, selector, selectorArgs ) => {
|
export const getError = (
|
||||||
|
state: ExportState,
|
||||||
|
selector: string,
|
||||||
|
selectorArgs: SelectorArgs
|
||||||
|
) => {
|
||||||
return (
|
return (
|
||||||
state.errors[ selector ] &&
|
state.errors[ selector ] &&
|
||||||
state.errors[ selector ][ hashExportArgs( selectorArgs ) ]
|
state.errors[ selector ][ hashExportArgs( selectorArgs ) ]
|
|
@ -18,6 +18,7 @@ const defaultState = {
|
||||||
|
|
||||||
describe( 'export reducer', () => {
|
describe( 'export reducer', () => {
|
||||||
it( 'should return a default state', () => {
|
it( 'should return a default state', () => {
|
||||||
|
// @ts-expect-error reducer action should not be empty but it is
|
||||||
const state = reducer( undefined, {} );
|
const state = reducer( undefined, {} );
|
||||||
expect( state ).toEqual( defaultState );
|
expect( state ).toEqual( defaultState );
|
||||||
expect( state ).not.toBe( 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
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { getResourceName } from '../utils';
|
import { getResourceName } from '../utils';
|
||||||
|
import { ExportArgs } from './types';
|
||||||
|
|
||||||
export const hashExportArgs = ( args ) => {
|
export const hashExportArgs = ( args: ExportArgs ) => {
|
||||||
return md5( getResourceName( 'export', args ) );
|
return md5( getResourceName( 'export', args ) );
|
||||||
};
|
};
|
|
@ -1,11 +1,11 @@
|
||||||
const TYPES = {
|
const TYPES = {
|
||||||
SET_IMPORT_DATE: 'SET_IMPORT_DATE',
|
SET_IMPORT_DATE: 'SET_IMPORT_DATE' as const,
|
||||||
SET_IMPORT_ERROR: 'SET_IMPORT_ERROR',
|
SET_IMPORT_ERROR: 'SET_IMPORT_ERROR' as const,
|
||||||
SET_IMPORT_PERIOD: 'SET_IMPORT_PERIOD',
|
SET_IMPORT_PERIOD: 'SET_IMPORT_PERIOD' as const,
|
||||||
SET_IMPORT_STARTED: 'SET_IMPORT_STARTED',
|
SET_IMPORT_STARTED: 'SET_IMPORT_STARTED' as const,
|
||||||
SET_IMPORT_STATUS: 'SET_IMPORT_STATUS',
|
SET_IMPORT_STATUS: 'SET_IMPORT_STATUS' as const,
|
||||||
SET_IMPORT_TOTALS: 'SET_IMPORT_TOTALS',
|
SET_IMPORT_TOTALS: 'SET_IMPORT_TOTALS' as const,
|
||||||
SET_SKIP_IMPORTED: 'SET_SKIP_IMPORTED',
|
SET_SKIP_IMPORTED: 'SET_SKIP_IMPORTED' as const,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TYPES;
|
export default TYPES;
|
||||||
|
|
|
@ -7,15 +7,21 @@ import { apiFetch } from '@wordpress/data-controls';
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import TYPES from './action-types';
|
import TYPES from './action-types';
|
||||||
|
import {
|
||||||
|
ImportStatusQuery,
|
||||||
|
ImportStatus,
|
||||||
|
ImportTotals,
|
||||||
|
ImportTotalsQuery,
|
||||||
|
} from './types';
|
||||||
|
|
||||||
export function setImportStarted( activeImport ) {
|
export function setImportStarted( activeImport: boolean ) {
|
||||||
return {
|
return {
|
||||||
type: TYPES.SET_IMPORT_STARTED,
|
type: TYPES.SET_IMPORT_STARTED,
|
||||||
activeImport,
|
activeImport,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setImportPeriod( date, dateModified ) {
|
export function setImportPeriod( date: string, dateModified: boolean ) {
|
||||||
if ( ! dateModified ) {
|
if ( ! dateModified ) {
|
||||||
return {
|
return {
|
||||||
type: TYPES.SET_IMPORT_PERIOD,
|
type: TYPES.SET_IMPORT_PERIOD,
|
||||||
|
@ -28,14 +34,17 @@ export function setImportPeriod( date, dateModified ) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setSkipPrevious( skipPrevious ) {
|
export function setSkipPrevious( skipPrevious: boolean ) {
|
||||||
return {
|
return {
|
||||||
type: TYPES.SET_SKIP_IMPORTED,
|
type: TYPES.SET_SKIP_IMPORTED,
|
||||||
skipPrevious,
|
skipPrevious,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setImportStatus( query, importStatus ) {
|
export function setImportStatus(
|
||||||
|
query: ImportStatusQuery,
|
||||||
|
importStatus: ImportStatus
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
type: TYPES.SET_IMPORT_STATUS,
|
type: TYPES.SET_IMPORT_STATUS,
|
||||||
importStatus,
|
importStatus,
|
||||||
|
@ -43,7 +52,10 @@ export function setImportStatus( query, importStatus ) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setImportTotals( query, importTotals ) {
|
export function setImportTotals(
|
||||||
|
query: ImportTotalsQuery,
|
||||||
|
importTotals: ImportTotals
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
type: TYPES.SET_IMPORT_TOTALS,
|
type: TYPES.SET_IMPORT_TOTALS,
|
||||||
importTotals,
|
importTotals,
|
||||||
|
@ -51,21 +63,33 @@ export function setImportTotals( query, importTotals ) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setImportError( query, error ) {
|
export function setImportError(
|
||||||
|
queryOrPath: ImportStatusQuery | ImportTotalsQuery | string,
|
||||||
|
error: unknown
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
type: TYPES.SET_IMPORT_ERROR,
|
type: TYPES.SET_IMPORT_ERROR,
|
||||||
error,
|
error,
|
||||||
query,
|
query: queryOrPath,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* updateImportation( path, importStarted = false ) {
|
export function* updateImportation( path: string, importStarted = false ) {
|
||||||
yield setImportStarted( importStarted );
|
yield setImportStarted( importStarted );
|
||||||
try {
|
try {
|
||||||
const response = yield apiFetch( { path, method: 'POST' } );
|
const response: unknown = yield apiFetch( { path, method: 'POST' } );
|
||||||
return response;
|
return response;
|
||||||
} catch ( error ) {
|
} catch ( error ) {
|
||||||
yield setImportError( path, error );
|
yield setImportError( path, error );
|
||||||
throw 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
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
export const STORE_NAME = 'wc/admin/import';
|
export const STORE_NAME = 'wc/admin/import' as const;
|
||||||
|
|
|
@ -1,25 +1,36 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { registerStore } from '@wordpress/data';
|
import { registerStore } from '@wordpress/data';
|
||||||
import { controls } from '@wordpress/data-controls';
|
import { controls } from '@wordpress/data-controls';
|
||||||
|
import { SelectFromMap, DispatchFromMap } from '@automattic/data-stores';
|
||||||
|
import { Reducer, AnyAction } from 'redux';
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import { STORE_NAME } from './constants';
|
import { STORE_NAME } from './constants';
|
||||||
import * as selectors from './selectors';
|
import * as selectors from './selectors';
|
||||||
import * as actions from './actions';
|
import * as actions from './actions';
|
||||||
import * as resolvers from './resolvers';
|
import reducer, { State } from './reducer';
|
||||||
import reducer from './reducer';
|
import { WPDataSelectors } from '../types';
|
||||||
|
export * from './types';
|
||||||
|
export type { State };
|
||||||
|
|
||||||
registerStore( STORE_NAME, {
|
registerStore< State >( STORE_NAME, {
|
||||||
reducer,
|
reducer: reducer as Reducer< State, AnyAction >,
|
||||||
actions,
|
actions,
|
||||||
controls,
|
controls,
|
||||||
selectors,
|
selectors,
|
||||||
resolvers,
|
|
||||||
} );
|
} );
|
||||||
|
|
||||||
export const IMPORT_STORE_NAME = STORE_NAME;
|
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 { __ } from '@wordpress/i18n';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
|
import type { Reducer } from 'redux';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import TYPES from './action-types';
|
import TYPES from './action-types';
|
||||||
|
import { ImportState } from './types';
|
||||||
|
import { Action } from './actions';
|
||||||
|
|
||||||
const reducer = (
|
const reducer: Reducer< ImportState, Action > = (
|
||||||
state = {
|
state = {
|
||||||
activeImport: false,
|
activeImport: false,
|
||||||
importStatus: {},
|
importStatus: {},
|
||||||
|
@ -22,19 +25,11 @@ const reducer = (
|
||||||
},
|
},
|
||||||
skipPrevious: true,
|
skipPrevious: true,
|
||||||
},
|
},
|
||||||
{
|
action
|
||||||
type,
|
|
||||||
query,
|
|
||||||
importStatus,
|
|
||||||
importTotals,
|
|
||||||
activeImport,
|
|
||||||
date,
|
|
||||||
error,
|
|
||||||
skipPrevious,
|
|
||||||
}
|
|
||||||
) => {
|
) => {
|
||||||
switch ( type ) {
|
switch ( action.type ) {
|
||||||
case TYPES.SET_IMPORT_STARTED:
|
case TYPES.SET_IMPORT_STARTED:
|
||||||
|
const { activeImport } = action;
|
||||||
state = {
|
state = {
|
||||||
...state,
|
...state,
|
||||||
activeImport,
|
activeImport,
|
||||||
|
@ -48,7 +43,7 @@ const reducer = (
|
||||||
...state,
|
...state,
|
||||||
period: {
|
period: {
|
||||||
...state.period,
|
...state.period,
|
||||||
label: date,
|
label: action.date,
|
||||||
},
|
},
|
||||||
activeImport: false,
|
activeImport: false,
|
||||||
};
|
};
|
||||||
|
@ -57,7 +52,7 @@ const reducer = (
|
||||||
state = {
|
state = {
|
||||||
...state,
|
...state,
|
||||||
period: {
|
period: {
|
||||||
date,
|
date: action.date,
|
||||||
label: 'custom',
|
label: 'custom',
|
||||||
},
|
},
|
||||||
activeImport: false,
|
activeImport: false,
|
||||||
|
@ -66,11 +61,12 @@ const reducer = (
|
||||||
case TYPES.SET_SKIP_IMPORTED:
|
case TYPES.SET_SKIP_IMPORTED:
|
||||||
state = {
|
state = {
|
||||||
...state,
|
...state,
|
||||||
skipPrevious,
|
skipPrevious: action.skipPrevious,
|
||||||
activeImport: false,
|
activeImport: false,
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case TYPES.SET_IMPORT_STATUS:
|
case TYPES.SET_IMPORT_STATUS:
|
||||||
|
const { query, importStatus } = action;
|
||||||
state = {
|
state = {
|
||||||
...state,
|
...state,
|
||||||
importStatus: {
|
importStatus: {
|
||||||
|
@ -88,7 +84,7 @@ const reducer = (
|
||||||
...state,
|
...state,
|
||||||
importTotals: {
|
importTotals: {
|
||||||
...state.importTotals,
|
...state.importTotals,
|
||||||
[ JSON.stringify( query ) ]: importTotals,
|
[ JSON.stringify( action.query ) ]: action.importTotals,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
@ -97,7 +93,7 @@ const reducer = (
|
||||||
...state,
|
...state,
|
||||||
errors: {
|
errors: {
|
||||||
...state.errors,
|
...state.errors,
|
||||||
[ JSON.stringify( query ) ]: error,
|
[ JSON.stringify( action.query ) ]: action.error,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
|
@ -105,4 +101,5 @@ const reducer = (
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type State = ReturnType< typeof reducer >;
|
||||||
export default reducer;
|
export default reducer;
|
|
@ -10,27 +10,33 @@ import { omit } from 'lodash';
|
||||||
*/
|
*/
|
||||||
import { NAMESPACE } from '../constants';
|
import { NAMESPACE } from '../constants';
|
||||||
import { setImportError, setImportStatus, setImportTotals } from './actions';
|
import { setImportError, setImportStatus, setImportTotals } from './actions';
|
||||||
|
import {
|
||||||
|
ImportStatusQuery,
|
||||||
|
ImportTotalsQuery,
|
||||||
|
ImportStatus,
|
||||||
|
ImportTotals,
|
||||||
|
} from './types';
|
||||||
|
|
||||||
export function* getImportStatus( query ) {
|
export function* getImportStatus( query: ImportStatusQuery ) {
|
||||||
try {
|
try {
|
||||||
const url = addQueryArgs(
|
const url = addQueryArgs(
|
||||||
`${ NAMESPACE }/reports/import/status`,
|
`${ 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 );
|
yield setImportStatus( query, response );
|
||||||
} catch ( error ) {
|
} catch ( error ) {
|
||||||
yield setImportError( query, error );
|
yield setImportError( query, error );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function* getImportTotals( query ) {
|
export function* getImportTotals( query: ImportTotalsQuery ) {
|
||||||
try {
|
try {
|
||||||
const url = addQueryArgs(
|
const url = addQueryArgs(
|
||||||
`${ NAMESPACE }/reports/import/totals`,
|
`${ NAMESPACE }/reports/import/totals`,
|
||||||
query
|
query
|
||||||
);
|
);
|
||||||
const response = yield apiFetch( { path: url } );
|
const response: ImportTotals = yield apiFetch( { path: url } );
|
||||||
yield setImportTotals( query, response );
|
yield setImportTotals( query, response );
|
||||||
} catch ( error ) {
|
} catch ( error ) {
|
||||||
yield setImportError( query, 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;
|
const { activeImport, lastImportStartTimestamp } = state;
|
||||||
return { activeImport, lastImportStartTimestamp } || {};
|
return { activeImport, lastImportStartTimestamp } || {};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getFormSettings = ( state ) => {
|
export const getFormSettings = ( state: ImportState ) => {
|
||||||
const { period, skipPrevious } = state;
|
const { period, skipPrevious } = state;
|
||||||
return { period, skipPrevious } || {};
|
return { period, skipPrevious } || {};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getImportStatus = ( state, query ) => {
|
export const getImportStatus = (
|
||||||
|
state: ImportState,
|
||||||
|
query: ImportStatusQuery
|
||||||
|
) => {
|
||||||
const stringifiedQuery = JSON.stringify( query );
|
const stringifiedQuery = JSON.stringify( query );
|
||||||
return state.importStatus[ stringifiedQuery ] || {};
|
return state.importStatus[ stringifiedQuery ] || {};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getImportTotals = ( state, query ) => {
|
export const getImportTotals = (
|
||||||
|
state: ImportState,
|
||||||
|
query: ImportTotalsQuery
|
||||||
|
) => {
|
||||||
const { importTotals, lastImportStartTimestamp } = state;
|
const { importTotals, lastImportStartTimestamp } = state;
|
||||||
const stringifiedQuery = JSON.stringify( query );
|
const stringifiedQuery = JSON.stringify( query );
|
||||||
return (
|
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 );
|
const stringifiedQuery = JSON.stringify( query );
|
||||||
return state.errors[ stringifiedQuery ] || false;
|
return state.errors[ stringifiedQuery ] || false;
|
||||||
};
|
};
|
|
@ -24,6 +24,7 @@ const defaultState = {
|
||||||
|
|
||||||
describe( 'import reducer', () => {
|
describe( 'import reducer', () => {
|
||||||
it( 'should return a default state', () => {
|
it( 'should return a default state', () => {
|
||||||
|
// @ts-expect-error reducer action should not be empty but it is
|
||||||
const state = reducer( undefined, {} );
|
const state = reducer( undefined, {} );
|
||||||
expect( state ).toEqual( defaultState );
|
expect( state ).toEqual( defaultState );
|
||||||
expect( state ).not.toBe( defaultState );
|
expect( state ).not.toBe( defaultState );
|
||||||
|
@ -113,7 +114,10 @@ describe( 'import reducer', () => {
|
||||||
error: { code: 'error' },
|
error: { code: 'error' },
|
||||||
} );
|
} );
|
||||||
const stringifiedQuery = JSON.stringify( query );
|
const stringifiedQuery = JSON.stringify( query );
|
||||||
|
expect(
|
||||||
expect( state.errors[ stringifiedQuery ].code ).toBe( 'error' );
|
( 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
|
'@babel/runtime': ^7.17.2
|
||||||
'@testing-library/react': ^12.1.3
|
'@testing-library/react': ^12.1.3
|
||||||
'@testing-library/react-hooks': ^7.0.2
|
'@testing-library/react-hooks': ^7.0.2
|
||||||
|
'@types/md5': ^2.3.2
|
||||||
'@types/wordpress__compose': ^4.0.1
|
'@types/wordpress__compose': ^4.0.1
|
||||||
'@types/wordpress__core-data': ^2.4.5
|
'@types/wordpress__core-data': ^2.4.5
|
||||||
'@types/wordpress__data': ^6.0.0
|
'@types/wordpress__data': ^6.0.0
|
||||||
|
@ -536,6 +537,7 @@ importers:
|
||||||
'@babel/runtime': 7.17.7
|
'@babel/runtime': 7.17.7
|
||||||
'@testing-library/react': 12.1.4
|
'@testing-library/react': 12.1.4
|
||||||
'@testing-library/react-hooks': 7.0.2
|
'@testing-library/react-hooks': 7.0.2
|
||||||
|
'@types/md5': 2.3.2
|
||||||
'@types/wordpress__compose': 4.0.1
|
'@types/wordpress__compose': 4.0.1
|
||||||
'@types/wordpress__core-data': 2.4.5
|
'@types/wordpress__core-data': 2.4.5
|
||||||
'@types/wordpress__data': 6.0.0
|
'@types/wordpress__data': 6.0.0
|
||||||
|
@ -13418,6 +13420,10 @@ packages:
|
||||||
/@types/lodash/4.14.180:
|
/@types/lodash/4.14.180:
|
||||||
resolution: {integrity: sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g==}
|
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:
|
/@types/mdast/3.0.10:
|
||||||
resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==}
|
resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -13711,6 +13717,7 @@ packages:
|
||||||
re-resizable: 4.11.0
|
re-resizable: 4.11.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- react
|
- react
|
||||||
|
- react-dom
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@types/wordpress__compose/4.0.1:
|
/@types/wordpress__compose/4.0.1:
|
||||||
|
@ -18577,7 +18584,7 @@ packages:
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/buffer-crc32/0.2.13:
|
/buffer-crc32/0.2.13:
|
||||||
resolution: {integrity: sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=}
|
resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
|
||||||
|
|
||||||
/buffer-fill/1.0.0:
|
/buffer-fill/1.0.0:
|
||||||
resolution: {integrity: sha1-+PeLdniYiO858gXNY39o5wISKyw=}
|
resolution: {integrity: sha1-+PeLdniYiO858gXNY39o5wISKyw=}
|
||||||
|
@ -39221,7 +39228,7 @@ packages:
|
||||||
tapable: 1.1.3
|
tapable: 1.1.3
|
||||||
terser-webpack-plugin: 1.4.5_webpack@4.46.0
|
terser-webpack-plugin: 1.4.5_webpack@4.46.0
|
||||||
watchpack: 1.7.5
|
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
|
webpack-sources: 1.4.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue