Use products data store for getPermalinkParts selector (#36706)

* Add generated_slug and permalink_template to Product

* Update getPermalinkParts to use products data store instead of posts data store

* Remove ts-expect-error directive

* Changelog

* Add resolver for getPermalinkParts
This commit is contained in:
Matt Sherman 2023-02-15 17:02:55 +01:00 committed by GitHub
parent 993f1f4879
commit e05a191156
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 36 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: update
Use products data store for getPermalinkParts selector.

View File

@ -19,7 +19,6 @@ registerStore< State >( STORE_NAME, {
reducer: reducer as Reducer< ProductState >, reducer: reducer as Reducer< ProductState >,
actions, actions,
controls, controls,
// @ts-expect-error as the registerStore type is not allowing the createRegistrySelector selector.
selectors, selectors,
resolvers, resolvers,
} ); } );

View File

@ -2,12 +2,17 @@
* External dependencies * External dependencies
*/ */
import { addQueryArgs } from '@wordpress/url'; import { addQueryArgs } from '@wordpress/url';
import { apiFetch } from '@wordpress/data-controls'; import {
apiFetch,
dispatch as deprecatedDispatch,
select,
} from '@wordpress/data-controls';
import { controls } from '@wordpress/data';
/** /**
* Internal dependencies * Internal dependencies
*/ */
import { WC_PRODUCT_NAMESPACE } from './constants'; import { STORE_NAME, WC_PRODUCT_NAMESPACE } from './constants';
import { Product, ProductQuery } from './types'; import { Product, ProductQuery } from './types';
import { import {
getProductError, getProductError,
@ -19,6 +24,11 @@ import {
} from './actions'; } from './actions';
import { request } from '../utils'; import { request } from '../utils';
const dispatch =
controls && controls.dispatch ? controls.dispatch : deprecatedDispatch;
const resolveSelect =
controls && controls.resolveSelect ? controls.resolveSelect : select;
export function* getProducts( query: Partial< ProductQuery > ) { export function* getProducts( query: Partial< ProductQuery > ) {
// id is always required. // id is always required.
const productsQuery = { const productsQuery = {
@ -56,6 +66,11 @@ export function* getProduct( productId: number ) {
} ); } );
yield getProductSuccess( productId, product ); yield getProductSuccess( productId, product );
yield dispatch( STORE_NAME, 'finishResolution', 'getPermalinkParts', [
productId,
] );
return product; return product;
} catch ( error ) { } catch ( error ) {
yield getProductError( productId, error ); yield getProductError( productId, error );
@ -81,3 +96,7 @@ export function* getProductsTotalCount( query: Partial< ProductQuery > ) {
throw error; throw error;
} }
} }
export function* getPermalinkParts( productId: number ) {
yield resolveSelect( STORE_NAME, 'getProduct', [ productId ] );
}

View File

@ -2,7 +2,6 @@
* External dependencies * External dependencies
*/ */
import createSelector from 'rememo'; import createSelector from 'rememo';
import { createRegistrySelector } from '@wordpress/data';
/** /**
* Internal dependencies * Internal dependencies
@ -122,38 +121,24 @@ export const isPending = (
return false; return false;
}; };
export const getPermalinkParts = createRegistrySelector( export const getPermalinkParts = ( state: ProductState, productId: number ) => {
( select ) => ( state: ProductState, productId: number ) => { const product = state.data[ productId ];
const product = select( 'core' ).getEntityRecord(
'postType', if ( product && product.permalink_template ) {
'product', const postName = product.slug || product.generated_slug;
productId,
// @ts-expect-error query object is not part of the @wordpress/core-data types yet. const [ prefix, suffix ] = product.permalink_template.split(
{ PERMALINK_PRODUCT_REGEX
_fields: [
'id',
'permalink_template',
'slug',
'generated_slug',
],
}
); );
if ( product && product.permalink_template ) {
const postName = product.slug || product.generated_slug;
const [ prefix, suffix ] = product.permalink_template.split( return {
PERMALINK_PRODUCT_REGEX prefix,
); postName,
suffix,
return { };
prefix,
postName,
suffix,
};
}
return null;
} }
); return null;
};
export type ProductsSelectors = { export type ProductsSelectors = {
getCreateProductError: WPDataSelector< typeof getCreateProductError >; getCreateProductError: WPDataSelector< typeof getCreateProductError >;
@ -162,7 +147,5 @@ export type ProductsSelectors = {
getProductsTotalCount: WPDataSelector< typeof getProductsTotalCount >; getProductsTotalCount: WPDataSelector< typeof getProductsTotalCount >;
getProductsError: WPDataSelector< typeof getProductsError >; getProductsError: WPDataSelector< typeof getProductsError >;
isPending: WPDataSelector< typeof isPending >; isPending: WPDataSelector< typeof isPending >;
getPermalinkParts: ( getPermalinkParts: WPDataSelector< typeof getPermalinkParts >;
productId: number
) => { prefix: string; postName: string; suffix: string } | null;
} & WPDataSelectors; } & WPDataSelectors;

View File

@ -66,6 +66,7 @@ export type Product< Status = ProductStatus, Type = ProductType > = Omit<
downloads: ProductDownload[]; downloads: ProductDownload[];
external_url: string; external_url: string;
featured: boolean; featured: boolean;
generated_slug: string;
id: number; id: number;
low_stock_amount: number; low_stock_amount: number;
manage_stock: boolean; manage_stock: boolean;
@ -73,6 +74,7 @@ export type Product< Status = ProductStatus, Type = ProductType > = Omit<
name: string; name: string;
on_sale: boolean; on_sale: boolean;
permalink: string; permalink: string;
permalink_template: string;
price: string; price: string;
price_html: string; price_html: string;
purchasable: boolean; purchasable: boolean;
@ -108,9 +110,11 @@ export const productReadOnlyProperties = [
'date_created_gmt', 'date_created_gmt',
'date_modified', 'date_modified',
'date_modified_gmt', 'date_modified_gmt',
'generated_slug',
'id', 'id',
'on_sale', 'on_sale',
'permalink', 'permalink',
'permalink_template',
'price', 'price',
'price_html', 'price_html',
'purchasable', 'purchasable',