Add create product actions in products data store (#33278)
* Add create product actions in products data store * Add changelog entry * Yield to actions in generator * Add mutable properties type
This commit is contained in:
parent
1bca9327ac
commit
17d9e8072d
|
@ -0,0 +1,4 @@
|
||||||
|
Significance: minor
|
||||||
|
Type: add
|
||||||
|
|
||||||
|
Add create product actions in products data store #33278
|
|
@ -155,3 +155,4 @@ export interface WCDataSelector {
|
||||||
|
|
||||||
// Other exports
|
// Other exports
|
||||||
export { ActionDispatchers as PluginsStoreActions } from './plugins/actions';
|
export { ActionDispatchers as PluginsStoreActions } from './plugins/actions';
|
||||||
|
export { ActionDispatchers as ProductsStoreActions } from './products/actions';
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
export enum TYPES {
|
export enum TYPES {
|
||||||
|
CREATE_PRODUCT_ERROR = 'CREATE_PRODUCT_ERROR',
|
||||||
|
CREATE_PRODUCT_SUCCESS = 'CREATE_PRODUCT_SUCCESS',
|
||||||
GET_PRODUCT_SUCCESS = 'GET_PRODUCT_SUCCESS',
|
GET_PRODUCT_SUCCESS = 'GET_PRODUCT_SUCCESS',
|
||||||
GET_PRODUCT_ERROR = 'GET_PRODUCT_ERROR',
|
GET_PRODUCT_ERROR = 'GET_PRODUCT_ERROR',
|
||||||
GET_PRODUCTS_SUCCESS = 'GET_PRODUCTS_SUCCESS',
|
GET_PRODUCTS_SUCCESS = 'GET_PRODUCTS_SUCCESS',
|
||||||
|
|
|
@ -1,8 +1,20 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import { apiFetch } from '@wordpress/data-controls';
|
||||||
|
import { DispatchFromMap } from '@automattic/data-stores';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import TYPES from './action-types';
|
import TYPES from './action-types';
|
||||||
import { PartialProduct, ProductQuery } from './types';
|
import {
|
||||||
|
MutableProperties,
|
||||||
|
PartialProduct,
|
||||||
|
Product,
|
||||||
|
ProductQuery,
|
||||||
|
} from './types';
|
||||||
|
import { WC_PRODUCT_NAMESPACE } from './constants';
|
||||||
|
|
||||||
export function getProductSuccess( id: number, product: PartialProduct ) {
|
export function getProductSuccess( id: number, product: PartialProduct ) {
|
||||||
return {
|
return {
|
||||||
|
@ -23,6 +35,25 @@ export function getProductError(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createProductSuccess( id: number, product: PartialProduct ) {
|
||||||
|
return {
|
||||||
|
type: TYPES.CREATE_PRODUCT_SUCCESS as const,
|
||||||
|
id,
|
||||||
|
product,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createProductError(
|
||||||
|
query: Partial< Product >,
|
||||||
|
error: unknown
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
type: TYPES.CREATE_PRODUCT_ERROR as const,
|
||||||
|
query,
|
||||||
|
error,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function getProductsSuccess(
|
export function getProductsSuccess(
|
||||||
query: Partial< ProductQuery >,
|
query: Partial< ProductQuery >,
|
||||||
products: PartialProduct[],
|
products: PartialProduct[],
|
||||||
|
@ -69,7 +100,25 @@ export function getProductsTotalCountError(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function* createProduct( data: Pick< Product, MutableProperties > ) {
|
||||||
|
try {
|
||||||
|
const product: Product = yield apiFetch( {
|
||||||
|
path: WC_PRODUCT_NAMESPACE,
|
||||||
|
method: 'POST',
|
||||||
|
data,
|
||||||
|
} );
|
||||||
|
|
||||||
|
yield createProductSuccess( product.id, product );
|
||||||
|
return product;
|
||||||
|
} catch ( error ) {
|
||||||
|
yield createProductError( data, error );
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export type Actions = ReturnType<
|
export type Actions = ReturnType<
|
||||||
|
| typeof createProductError
|
||||||
|
| typeof createProductSuccess
|
||||||
| typeof getProductSuccess
|
| typeof getProductSuccess
|
||||||
| typeof getProductError
|
| typeof getProductError
|
||||||
| typeof getProductsSuccess
|
| typeof getProductsSuccess
|
||||||
|
@ -77,3 +126,7 @@ export type Actions = ReturnType<
|
||||||
| typeof getProductsTotalCountSuccess
|
| typeof getProductsTotalCountSuccess
|
||||||
| typeof getProductsTotalCountError
|
| typeof getProductsTotalCountError
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
export type ActionDispatchers = DispatchFromMap< {
|
||||||
|
createProduct: typeof createProduct;
|
||||||
|
} >;
|
||||||
|
|
|
@ -37,6 +37,7 @@ const reducer: Reducer< ProductState, Actions > = (
|
||||||
) => {
|
) => {
|
||||||
if ( payload && 'type' in payload ) {
|
if ( payload && 'type' in payload ) {
|
||||||
switch ( payload.type ) {
|
switch ( payload.type ) {
|
||||||
|
case TYPES.CREATE_PRODUCT_SUCCESS:
|
||||||
case TYPES.GET_PRODUCT_SUCCESS:
|
case TYPES.GET_PRODUCT_SUCCESS:
|
||||||
const productData = state.data || {};
|
const productData = state.data || {};
|
||||||
return {
|
return {
|
||||||
|
@ -88,6 +89,7 @@ const reducer: Reducer< ProductState, Actions > = (
|
||||||
case TYPES.GET_PRODUCT_ERROR:
|
case TYPES.GET_PRODUCT_ERROR:
|
||||||
case TYPES.GET_PRODUCTS_ERROR:
|
case TYPES.GET_PRODUCTS_ERROR:
|
||||||
case TYPES.GET_PRODUCTS_TOTAL_COUNT_ERROR:
|
case TYPES.GET_PRODUCTS_TOTAL_COUNT_ERROR:
|
||||||
|
case TYPES.CREATE_PRODUCT_ERROR:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
errors: {
|
errors: {
|
||||||
|
|
|
@ -77,7 +77,16 @@ export const getProductsError = (
|
||||||
return state.errors[ resourceName ];
|
return state.errors[ resourceName ];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getCreateProductError = (
|
||||||
|
state: ProductState,
|
||||||
|
query: ProductQuery
|
||||||
|
) => {
|
||||||
|
const resourceName = getProductResourceName( query );
|
||||||
|
return state.errors[ resourceName ];
|
||||||
|
};
|
||||||
|
|
||||||
export type ProductsSelectors = {
|
export type ProductsSelectors = {
|
||||||
|
getCreateProductError: WPDataSelector< typeof getCreateProductError >;
|
||||||
getProducts: WPDataSelector< typeof getProducts >;
|
getProducts: WPDataSelector< typeof getProducts >;
|
||||||
getProductsTotalCount: WPDataSelector< typeof getProductsTotalCount >;
|
getProductsTotalCount: WPDataSelector< typeof getProductsTotalCount >;
|
||||||
getProductsError: WPDataSelector< typeof getProductsError >;
|
getProductsError: WPDataSelector< typeof getProductsError >;
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
getTotalProductCountResourceName,
|
getTotalProductCountResourceName,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { Actions } from '../actions';
|
import { Actions } from '../actions';
|
||||||
import { PartialProduct, ProductQuery } from '../types';
|
import { PartialProduct, ProductQuery, Product } from '../types';
|
||||||
|
|
||||||
const defaultState: ProductState = {
|
const defaultState: ProductState = {
|
||||||
products: {},
|
products: {},
|
||||||
|
@ -180,4 +180,34 @@ describe( 'products reducer', () => {
|
||||||
|
|
||||||
expect( state.errors[ resourceName ] ).toBe( error );
|
expect( state.errors[ resourceName ] ).toBe( error );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
it( 'should handle CREATE_PRODUCT_SUCCESS', () => {
|
||||||
|
const update: PartialProduct = {
|
||||||
|
id: 2,
|
||||||
|
name: 'Off the hook!',
|
||||||
|
status: 'draft',
|
||||||
|
};
|
||||||
|
|
||||||
|
const state = reducer( defaultState, {
|
||||||
|
type: TYPES.CREATE_PRODUCT_SUCCESS,
|
||||||
|
id: update.id,
|
||||||
|
product: update,
|
||||||
|
} );
|
||||||
|
|
||||||
|
expect( state.data[ 2 ].name ).toEqual( update.name );
|
||||||
|
expect( state.data[ 2 ].status ).toEqual( update.status );
|
||||||
|
} );
|
||||||
|
|
||||||
|
it( 'should handle CREATE_PRODUCT_ERROR', () => {
|
||||||
|
const query: Partial< Product > = { name: 'Donkey Sauce' };
|
||||||
|
const resourceName = getProductResourceName( query );
|
||||||
|
const error = 'Baaam!';
|
||||||
|
const state = reducer( defaultState, {
|
||||||
|
type: TYPES.GET_PRODUCTS_ERROR,
|
||||||
|
query,
|
||||||
|
error,
|
||||||
|
} );
|
||||||
|
|
||||||
|
expect( state.errors[ resourceName ] ).toBe( error );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
|
@ -40,6 +40,18 @@ export type Product<
|
||||||
sale_price: string;
|
sale_price: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type MutableProperties =
|
||||||
|
| 'name'
|
||||||
|
| 'slug'
|
||||||
|
| 'type'
|
||||||
|
| 'status'
|
||||||
|
| 'featured'
|
||||||
|
| 'description'
|
||||||
|
| 'short_description'
|
||||||
|
| 'sku'
|
||||||
|
| 'regular_price'
|
||||||
|
| 'sale_price';
|
||||||
|
|
||||||
export type PartialProduct = Partial< Product > & Pick< Product, 'id' >;
|
export type PartialProduct = Partial< Product > & Pick< Product, 'id' >;
|
||||||
|
|
||||||
export type ProductQuery<
|
export type ProductQuery<
|
||||||
|
|
Loading…
Reference in New Issue