* Add previews for Reviews blocks

* Use double negation instead of Boolean

* Refactor withReviews to use class properties

* Fix tests

* Make example data translatable
This commit is contained in:
Albert Juhé Lluveras 2019-10-22 16:13:14 +02:00 committed by GitHub
parent 2fde552e3f
commit 15b330d36e
8 changed files with 153 additions and 40 deletions

View File

@ -50,6 +50,7 @@ const TestComponent = withReviews( ( props ) => {
const render = () => {
return TestRenderer.create(
<TestComponent
attributes={ {} }
order="desc"
orderby="date_gmt"
productId={ 1 }

View File

@ -13,21 +13,43 @@ import { formatError } from '../utils/errors.js';
const withReviews = ( OriginalComponent ) => {
class WrappedComponent extends Component {
constructor() {
super( ...arguments );
this.state = {
error: null,
loading: true,
reviews: [],
totalReviews: 0,
static propTypes = {
order: PropTypes.oneOf( [ 'asc', 'desc' ] ).isRequired,
orderby: PropTypes.string.isRequired,
reviewsToDisplay: PropTypes.number.isRequired,
categoryIds: PropTypes.oneOfType( [
PropTypes.string,
PropTypes.array,
] ),
delayFunction: PropTypes.func,
onReviewsAppended: PropTypes.func,
onReviewsLoadError: PropTypes.func,
onReviewsReplaced: PropTypes.func,
productId: PropTypes.oneOfType( [
PropTypes.string,
PropTypes.number,
] ),
};
this.setError = this.setError.bind( this );
this.delayedAppendReviews = this.props.delayFunction(
this.appendReviews
);
}
static defaultProps = {
delayFunction: ( f ) => f,
onReviewsAppended: () => {},
onReviewsLoadError: () => {},
onReviewsReplaced: () => {},
};
isPreview = !! this.props.attributes.previewReviews;
delayedAppendReviews = this.props.delayFunction( this.appendReviews );
state = {
error: null,
loading: true,
reviews: this.isPreview ? this.props.attributes.previewReviews : [],
totalReviews: this.isPreview
? this.props.attributes.previewReviews.length
: 0,
};
componentDidMount() {
this.replaceReviews();
@ -88,12 +110,20 @@ const withReviews = ( OriginalComponent ) => {
}
replaceReviews() {
if ( this.isPreview ) {
return;
}
const { onReviewsReplaced } = this.props;
this.updateListOfReviews().then( onReviewsReplaced );
}
appendReviews() {
if ( this.isPreview ) {
return;
}
const { onReviewsAppended, reviewsToDisplay } = this.props;
const { reviews } = this.state;
@ -140,14 +170,14 @@ const withReviews = ( OriginalComponent ) => {
.catch( this.setError );
}
async setError( e ) {
setError = async ( e ) => {
const { onReviewsLoadError } = this.props;
const error = await formatError( e );
this.setState( { reviews: [], loading: false, error } );
onReviewsLoadError( error );
}
};
render() {
const { reviewsToDisplay } = this.props;
@ -165,31 +195,6 @@ const withReviews = ( OriginalComponent ) => {
}
}
WrappedComponent.propTypes = {
order: PropTypes.oneOf( [ 'asc', 'desc' ] ).isRequired,
orderby: PropTypes.string.isRequired,
reviewsToDisplay: PropTypes.number.isRequired,
categoryIds: PropTypes.oneOfType( [
PropTypes.string,
PropTypes.array,
] ),
delayFunction: PropTypes.func,
onReviewsAppended: PropTypes.func,
onReviewsLoadError: PropTypes.func,
onReviewsReplaced: PropTypes.func,
productId: PropTypes.oneOfType( [
PropTypes.string,
PropTypes.number,
] ),
};
WrappedComponent.defaultProps = {
delayFunction: ( f ) => f,
onReviewsAppended: () => {},
onReviewsLoadError: () => {},
onReviewsReplaced: () => {},
};
const {
displayName = OriginalComponent.name || 'Component',
} = OriginalComponent;

View File

@ -12,6 +12,7 @@ import Editor from './edit';
import { IconAllReviews } from '@woocommerce/block-components/icons';
import sharedAttributes from '../attributes';
import save from '../save.js';
import { example } from '../example';
/**
* Register and run the "All Reviews" block.
@ -28,6 +29,13 @@ registerBlockType( 'woocommerce/all-reviews', {
'Shows a list of all product reviews.',
'woo-gutenberg-products-block'
),
example: {
...example,
attributes: {
...example.attributes,
showProductName: true,
},
},
attributes: {
...sharedAttributes,
/**

View File

@ -94,4 +94,9 @@ export default {
type: 'boolean',
default: true,
},
previewReviews: {
type: 'array',
default: null,
},
};

View File

@ -0,0 +1,19 @@
import { previewReviews } from '../../previews/reviews';
export const example = {
attributes: {
editMode: false,
imageType: 'reviewer',
orderby: 'most-recent',
reviewsOnLoadMore: 10,
reviewsOnPageLoad: 10,
showLoadMore: true,
showOrderby: true,
showReviewDate: true,
showReviewerName: true,
showReviewImage: true,
showReviewRating: true,
showReviewContent: true,
previewReviews,
},
};

View File

@ -12,6 +12,7 @@ import Editor from './edit';
import { IconReviewsByCategory } from '@woocommerce/block-components/icons';
import sharedAttributes from '../attributes';
import save from '../save.js';
import { example } from '../example';
/**
* Register and run the "Reviews by category" block.
@ -28,6 +29,14 @@ registerBlockType( 'woocommerce/reviews-by-category', {
'Show product reviews from specific categories.',
'woo-gutenberg-products-block'
),
example: {
...example,
attributes: {
...example.attributes,
categoryIds: [ 1 ],
showProductName: true,
},
},
attributes: {
...sharedAttributes,
/**

View File

@ -12,6 +12,7 @@ import Editor from './edit';
import { IconReviewsByProduct } from '@woocommerce/block-components/icons';
import sharedAttributes from '../attributes';
import save from '../save.js';
import { example } from '../example';
/**
* Register and run the "Reviews by Product" block.
@ -28,6 +29,13 @@ registerBlockType( 'woocommerce/reviews-by-product', {
'Show reviews of your product to build trust.',
'woo-gutenberg-products-block'
),
example: {
...example,
attributes: {
...example.attributes,
productId: 1,
},
},
attributes: {
...sharedAttributes,
/**

View File

@ -0,0 +1,58 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
const avatarPicture =
'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//gA7Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcgSlBFRyB2NjIpLCBxdWFsaXR5ID0gOTAK/9sAQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4LCxAWEBETFBUVFQwPFxgWFBgSFBUU/9sAQwEDBAQFBAUJBQUJFA0LDRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU/8AAEQgAMAAwAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A+t6KKtaXps2sahBZ24DTTNtXPQepPsBzQBVo/OvddD+H2j6Nbqr2sd7Pj5prhQ2T7A8Cl1z4f6PrNuyrax2c+Plmt1CkH3A4NAHhP50Vb1bTJtG1G4srgASwttOOh9CPYjBqp+VABXX/AAreNfF8If7zROEz/ex/hmuQq1pT3cepW7WAdrxXBiEYyS30oA+kKKp6RPeXOnwyX9strdEfPErBgD9f6UurT3dtp80ljbC7ugPkiZgoJ+tAHkHxWeNvFsgT7ywoHx/e6/yIrj6t6vJdy6lcvfh1vGcmUSDBB+lVKACvbvh/4Qj8PaYlxOgOozrudmHMYPRB/X3+leVeDrBdT8UabbuNyGUMwPcL8xH6V9BUAJRRRQByfxA8IR+IdMe4gjA1GBSyMo5kA6of6e/1rxGvpr/PWvn3xjYLpnijUrdBtQTFlHoGG4D9aAP/2Q==';
export const previewReviews = [
{
id: 1,
date_created: '2019-07-15T17:05:04',
formatted_date_created: __(
'July 15, 2019',
'woo-gutenberg-products-block'
),
date_created_gmt: '2019-07-15T15:05:04',
product_id: 0,
product_name: __( 'WordPress Pennant', 'woo-gutenberg-products-block' ),
product_permalink: '#',
/* translators: An example person name used for the block previews. */
reviewer: __( 'Alice', 'woo-gutenberg-products-block' ),
review: `<p>${ __(
"I bought this product last week and I'm very happy with it.",
'woo-gutenberg-products-block'
) }</p>\n`,
reviewer_avatar_urls: {
'48': avatarPicture,
'96': avatarPicture,
},
rating: 5,
verified: true,
},
{
id: 2,
date_created: '2019-07-12T12:39:39',
formatted_date_created: __(
'July 12, 2019',
'woo-gutenberg-products-block'
),
date_created_gmt: '2019-07-12T10:39:39',
product_id: 0,
product_name: __( 'WordPress Pennant', 'woo-gutenberg-products-block' ),
product_permalink: '#',
/* translators: An example person name used for the block previews. */
reviewer: __( 'Bob', 'woo-gutenberg-products-block' ),
review: `<p>${ __(
'This product is awesome, I love it!',
'woo-gutenberg-products-block'
) }</p>\n`,
reviewer_avatar_urls: {
'48': avatarPicture,
'96': avatarPicture,
},
rating: null,
verified: false,
},
];