Convert Reviews component to TypeScript (https://github.com/woocommerce/woocommerce-blocks/pull/7936)
* Convert review-sort-select to TS. * Convert review-list and review-list-item to TS. * Fix reviewer_avatar_urls type * Fix TypeScript errors * Fix TypeScript errors in frontend-block.js * Update assets/js/base/components/reviews/review-sort-select/index.tsx Co-authored-by: Luigi Teschio <gigitux@gmail.com> * Update assets/js/base/components/reviews/types.ts Co-authored-by: Luigi Teschio <gigitux@gmail.com> * fix Review type and remove index file details * fix ReviewSortSelect component 'value' prop type * fix typo Co-authored-by: Luigi Teschio <gigitux@gmail.com>
This commit is contained in:
parent
101034c4f0
commit
7a4fa29f0c
|
@ -1,3 +1,3 @@
|
|||
export { default as ReviewList } from './review-list';
|
||||
export { default as ReviewListItem } from './review-list-item';
|
||||
export { default as ReviewSortSelect } from './review-sort-select';
|
||||
export { default as ReviewList } from './review-list/';
|
||||
export { default as ReviewListItem } from './review-list-item/';
|
||||
export { default as ReviewSortSelect } from './review-sort-select/';
|
||||
|
|
|
@ -2,16 +2,21 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import ReadMore from '@woocommerce/base-components/read-more';
|
||||
import type { BlockAttributes } from '@wordpress/blocks';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
import type { Review } from '../types';
|
||||
|
||||
function getReviewImage( review, imageType, isLoading ) {
|
||||
function getReviewImage(
|
||||
review: Review,
|
||||
imageType: string,
|
||||
isLoading: boolean
|
||||
): JSX.Element {
|
||||
if ( isLoading || ! review ) {
|
||||
return (
|
||||
<div className="wc-block-review-list-item__image wc-block-components-review-list-item__image" />
|
||||
|
@ -51,7 +56,7 @@ function getReviewImage( review, imageType, isLoading ) {
|
|||
);
|
||||
}
|
||||
|
||||
function getReviewContent( review ) {
|
||||
function getReviewContent( review: Review ): JSX.Element {
|
||||
return (
|
||||
<ReadMore
|
||||
maxLines={ 10 }
|
||||
|
@ -77,7 +82,7 @@ function getReviewContent( review ) {
|
|||
);
|
||||
}
|
||||
|
||||
function getReviewProductName( review ) {
|
||||
function getReviewProductName( review: Review ): JSX.Element {
|
||||
return (
|
||||
<div className="wc-block-review-list-item__product wc-block-components-review-list-item__product">
|
||||
<a
|
||||
|
@ -93,7 +98,7 @@ function getReviewProductName( review ) {
|
|||
);
|
||||
}
|
||||
|
||||
function getReviewerName( review ) {
|
||||
function getReviewerName( review: Review ): JSX.Element {
|
||||
const { reviewer = '' } = review;
|
||||
return (
|
||||
<div className="wc-block-review-list-item__author wc-block-components-review-list-item__author">
|
||||
|
@ -102,7 +107,7 @@ function getReviewerName( review ) {
|
|||
);
|
||||
}
|
||||
|
||||
function getReviewDate( review ) {
|
||||
function getReviewDate( review: Review ): JSX.Element {
|
||||
const {
|
||||
date_created: dateCreated,
|
||||
formatted_date_created: formattedDateCreated,
|
||||
|
@ -117,7 +122,7 @@ function getReviewDate( review ) {
|
|||
);
|
||||
}
|
||||
|
||||
function getReviewRating( review ) {
|
||||
function getReviewRating( review: Review ): JSX.Element {
|
||||
const { rating } = review;
|
||||
const starStyle = {
|
||||
width: ( rating / 5 ) * 100 + '%' /* stylelint-disable-line */,
|
||||
|
@ -149,8 +154,12 @@ function getReviewRating( review ) {
|
|||
</div>
|
||||
);
|
||||
}
|
||||
interface ReviewListItemProps {
|
||||
attributes: BlockAttributes;
|
||||
review?: Review;
|
||||
}
|
||||
|
||||
const ReviewListItem = ( { attributes, review = {} } ) => {
|
||||
const ReviewListItem = ( { attributes, review = {} }: ReviewListItemProps ) => {
|
||||
const {
|
||||
imageType,
|
||||
showReviewDate,
|
||||
|
@ -161,7 +170,7 @@ const ReviewListItem = ( { attributes, review = {} } ) => {
|
|||
showProductName,
|
||||
} = attributes;
|
||||
const { rating } = review;
|
||||
const isLoading = ! Object.keys( review ).length > 0;
|
||||
const isLoading = ! ( Object.keys( review ).length > 0 );
|
||||
const showReviewRating = Number.isFinite( rating ) && showReviewRatingAttr;
|
||||
|
||||
return (
|
||||
|
@ -204,11 +213,6 @@ const ReviewListItem = ( { attributes, review = {} } ) => {
|
|||
);
|
||||
};
|
||||
|
||||
ReviewListItem.propTypes = {
|
||||
attributes: PropTypes.object.isRequired,
|
||||
review: PropTypes.object,
|
||||
};
|
||||
|
||||
/**
|
||||
* BE AWARE. ReviewListItem expects product data that is equivalent to what is
|
||||
* made available for output in a public view. Thus content that may contain
|
|
@ -1,16 +1,25 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import PropTypes from 'prop-types';
|
||||
import { getSetting } from '@woocommerce/settings';
|
||||
import type { BlockAttributes } from '@wordpress/blocks';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import ReviewListItem from '../review-list-item';
|
||||
import type { Review } from '../types';
|
||||
import './style.scss';
|
||||
|
||||
const ReviewList = ( { attributes, reviews } ) => {
|
||||
interface ReviewListProps {
|
||||
attributes: BlockAttributes;
|
||||
reviews: Review[];
|
||||
}
|
||||
|
||||
const ReviewList = ( {
|
||||
attributes,
|
||||
reviews,
|
||||
}: ReviewListProps ): JSX.Element => {
|
||||
const showAvatars = getSetting( 'showAvatars', true );
|
||||
const reviewRatingsEnabled = getSetting( 'reviewRatingsEnabled', true );
|
||||
const showReviewImage =
|
||||
|
@ -41,9 +50,4 @@ const ReviewList = ( { attributes, reviews } ) => {
|
|||
);
|
||||
};
|
||||
|
||||
ReviewList.propTypes = {
|
||||
attributes: PropTypes.object.isRequired,
|
||||
reviews: PropTypes.array.isRequired,
|
||||
};
|
||||
|
||||
export default ReviewList;
|
|
@ -2,15 +2,25 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import PropTypes from 'prop-types';
|
||||
import SortSelect from '@woocommerce/base-components/sort-select';
|
||||
import { ChangeEventHandler } from 'react';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
|
||||
const ReviewSortSelect = ( { onChange, readOnly, value } ) => {
|
||||
interface ReviewSortSelectProps {
|
||||
onChange: ChangeEventHandler;
|
||||
readOnly: boolean;
|
||||
value: 'most-recent' | 'highest-rating' | 'lowest-rating';
|
||||
}
|
||||
|
||||
const ReviewSortSelect = ( {
|
||||
onChange,
|
||||
readOnly,
|
||||
value,
|
||||
}: ReviewSortSelectProps ): JSX.Element => {
|
||||
return (
|
||||
<SortSelect
|
||||
className="wc-block-review-sort-select wc-block-components-review-sort-select"
|
||||
|
@ -46,14 +56,4 @@ const ReviewSortSelect = ( { onChange, readOnly, value } ) => {
|
|||
);
|
||||
};
|
||||
|
||||
ReviewSortSelect.propTypes = {
|
||||
onChange: PropTypes.func,
|
||||
readOnly: PropTypes.bool,
|
||||
value: PropTypes.oneOf( [
|
||||
'most-recent',
|
||||
'highest-rating',
|
||||
'lowest-rating',
|
||||
] ),
|
||||
};
|
||||
|
||||
export default ReviewSortSelect;
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { EmptyObjectType } from '@woocommerce/types';
|
||||
|
||||
export type Review =
|
||||
| {
|
||||
date_created: string;
|
||||
date_created_gmt: string;
|
||||
formatted_date_created: string;
|
||||
product_name: string;
|
||||
product_permalink: string;
|
||||
review: string;
|
||||
reviewer: string;
|
||||
id: number;
|
||||
product_id: number;
|
||||
product_image: {
|
||||
alt: string;
|
||||
thumbnail: string;
|
||||
name: string;
|
||||
sizes: string;
|
||||
src: string;
|
||||
srcset: string;
|
||||
};
|
||||
reviewer_avatar_urls: { [ size: string ]: string };
|
||||
verified: boolean;
|
||||
rating: number;
|
||||
}
|
||||
| EmptyObjectType;
|
|
@ -43,6 +43,11 @@ interface SortSelectProps {
|
|||
* The selected value.
|
||||
*/
|
||||
value?: string;
|
||||
|
||||
/**
|
||||
* Whether the select is read only.
|
||||
*/
|
||||
readOnly?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,7 +57,11 @@ class EditorBlock extends Component {
|
|||
return (
|
||||
<Disabled>
|
||||
{ attributes.showOrderby && reviewRatingsEnabled && (
|
||||
<ReviewSortSelect readOnly value={ attributes.orderby } />
|
||||
<ReviewSortSelect
|
||||
readOnly
|
||||
value={ attributes.orderby }
|
||||
onChange={ () => null }
|
||||
/>
|
||||
) }
|
||||
<ReviewList attributes={ attributes } reviews={ reviews } />
|
||||
{ attributes.showLoadMore && totalReviews > reviews.length && (
|
||||
|
|
|
@ -14,13 +14,13 @@ import withReviews from '@woocommerce/base-hocs/with-reviews';
|
|||
/**
|
||||
* Block rendered in the frontend.
|
||||
*
|
||||
* @param {Object} props Incoming props for the component.
|
||||
* @param {Object} props.attributes Incoming block attributes.
|
||||
* @param {function(any):any} props.onAppendReviews Function called when appending review.
|
||||
* @param {function(any):any} props.onChangeOrderby
|
||||
* @param {Array} props.reviews
|
||||
* @param {string} props.sortSelectValue
|
||||
* @param {number} props.totalReviews
|
||||
* @param {Object} props Incoming props for the component.
|
||||
* @param {Object} props.attributes Incoming block attributes.
|
||||
* @param {function(any):any} props.onAppendReviews Function called when appending review.
|
||||
* @param {function(any):any} props.onChangeOrderby
|
||||
* @param {Array} props.reviews
|
||||
* @param {'most-recent' | 'highest-rating' | 'lowest-rating'} props.sortSelectValue
|
||||
* @param {number} props.totalReviews
|
||||
*/
|
||||
const FrontendBlock = ( {
|
||||
attributes,
|
||||
|
@ -42,6 +42,7 @@ const FrontendBlock = ( {
|
|||
<ReviewSortSelect
|
||||
value={ sortSelectValue }
|
||||
onChange={ onChangeOrderby }
|
||||
readOnly
|
||||
/>
|
||||
) }
|
||||
<ReviewList attributes={ attributes } reviews={ reviews } />
|
||||
|
|
|
@ -1711,7 +1711,7 @@
|
|||
Type '0 | Element' is not assignable to type 'ReactElement<any, any> | null'.
|
||||
Type 'number' is not assignable to type 'ReactElement<any, any>'." source="TS2345" />
|
||||
</file>
|
||||
<file name="assets/js/base/components/reviews/review-list-item/index.js">
|
||||
<file name="assets/js/base/components/reviews/review-list-item/index.tsx">
|
||||
<error line="14" column="26" severity="error" message="Parameter 'review' implicitly has an 'any' type." source="TS7006" />
|
||||
<error line="14" column="34" severity="error" message="Parameter 'imageType' implicitly has an 'any' type." source="TS7006" />
|
||||
<error line="14" column="45" severity="error" message="Parameter 'isLoading' implicitly has an 'any' type." source="TS7006" />
|
||||
|
@ -1724,7 +1724,7 @@
|
|||
<error line="163" column="10" severity="error" message="Property 'rating' does not exist on type '{}'." source="TS2339" />
|
||||
<error line="164" column="20" severity="error" message="Operator '>' cannot be applied to types 'boolean' and 'number'." source="TS2365" />
|
||||
</file>
|
||||
<file name="assets/js/base/components/reviews/review-list/index.js">
|
||||
<file name="assets/js/base/components/reviews/review-list/index.tsx">
|
||||
<error line="13" column="24" severity="error" message="Binding element 'attributes' implicitly has an 'any' type." source="TS7031" />
|
||||
<error line="13" column="36" severity="error" message="Binding element 'reviews' implicitly has an 'any' type." source="TS7031" />
|
||||
<error line="32" column="20" severity="error" message="Parameter 'review' implicitly has an 'any' type." source="TS7006" />
|
||||
|
|
Loading…
Reference in New Issue