Activity Panel: set reviews unread indicator based on real data (https://github.com/woocommerce/woocommerce-admin/pull/1860)
* Activity Panel: set reviews unread indicator based on real data * Unify date comparisons to GMT * Add numberOfReviews propType * Verify date_created_gmt exists before using it
This commit is contained in:
parent
9038bdfdae
commit
41e5d00708
|
@ -92,7 +92,7 @@ class ActivityPanel extends Component {
|
|||
|
||||
// @todo Pull in dynamic unread status/count
|
||||
getTabs() {
|
||||
const { unreadNotes, unreadOrders } = this.props;
|
||||
const { unreadNotes, unreadOrders, unreadReviews } = this.props;
|
||||
return [
|
||||
{
|
||||
name: 'inbox',
|
||||
|
@ -119,7 +119,7 @@ class ActivityPanel extends Component {
|
|||
name: 'reviews',
|
||||
title: __( 'Reviews', 'woocommerce-admin' ),
|
||||
icon: <Gridicon icon="star" />,
|
||||
unread: false,
|
||||
unread: unreadReviews,
|
||||
}
|
||||
: null,
|
||||
].filter( Boolean );
|
||||
|
@ -135,7 +135,8 @@ class ActivityPanel extends Component {
|
|||
case 'stock':
|
||||
return <StockPanel />;
|
||||
case 'reviews':
|
||||
return <ReviewsPanel />;
|
||||
const { numberOfReviews } = this.props;
|
||||
return <ReviewsPanel numberOfReviews={ numberOfReviews } />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -270,12 +271,16 @@ export default withSelect( select => {
|
|||
getReportItemsError,
|
||||
isGetNotesRequesting,
|
||||
isReportItemsRequesting,
|
||||
getReviews,
|
||||
getReviewsTotalCount,
|
||||
getReviewsError,
|
||||
isGetReviewsRequesting,
|
||||
} = select( 'wc-api' );
|
||||
const userData = getCurrentUserData();
|
||||
const orderStatuses = wcSettings.wcAdminSettings.woocommerce_actionable_order_statuses || [
|
||||
'processing',
|
||||
'on-hold',
|
||||
];
|
||||
const userData = getCurrentUserData();
|
||||
|
||||
const notesQuery = {
|
||||
page: 1,
|
||||
|
@ -290,29 +295,52 @@ export default withSelect( select => {
|
|||
new Date( latestNote[ 0 ].date_created_gmt ).getTime() >
|
||||
userData.activity_panel_inbox_last_read;
|
||||
|
||||
if ( ! orderStatuses.length ) {
|
||||
return { unreadNotes, unreadOrders: false };
|
||||
}
|
||||
|
||||
const ordersQuery = {
|
||||
page: 1,
|
||||
per_page: 0,
|
||||
status_is: orderStatuses,
|
||||
};
|
||||
|
||||
const totalOrders = getReportItems( 'orders', ordersQuery ).totalResults;
|
||||
const isError = Boolean( getReportItemsError( 'orders', ordersQuery ) );
|
||||
const isRequesting = isReportItemsRequesting( 'orders', ordersQuery );
|
||||
|
||||
let unreadOrders = null;
|
||||
if ( ! orderStatuses.length ) {
|
||||
unreadOrders = false;
|
||||
} else {
|
||||
const ordersQuery = {
|
||||
page: 1,
|
||||
per_page: 0,
|
||||
status_is: orderStatuses,
|
||||
};
|
||||
|
||||
if ( ! isError && ! isRequesting ) {
|
||||
if ( totalOrders > 0 ) {
|
||||
unreadOrders = true;
|
||||
} else {
|
||||
unreadOrders = false;
|
||||
const totalOrders = getReportItems( 'orders', ordersQuery ).totalResults;
|
||||
const isOrdersError = Boolean( getReportItemsError( 'orders', ordersQuery ) );
|
||||
const isOrdersRequesting = isReportItemsRequesting( 'orders', ordersQuery );
|
||||
|
||||
if ( ! isOrdersError && ! isOrdersRequesting ) {
|
||||
if ( totalOrders > 0 ) {
|
||||
unreadOrders = true;
|
||||
} else {
|
||||
unreadOrders = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { unreadNotes, unreadOrders };
|
||||
let numberOfReviews = null;
|
||||
let unreadReviews = false;
|
||||
if ( 'yes' === wcSettings.reviewsEnabled ) {
|
||||
const reviewsQuery = {
|
||||
order: 'desc',
|
||||
orderby: 'date_gmt',
|
||||
page: 1,
|
||||
per_page: 1,
|
||||
};
|
||||
const reviews = getReviews( reviewsQuery );
|
||||
const totalReviews = getReviewsTotalCount( reviewsQuery );
|
||||
const isReviewsError = Boolean( getReviewsError( reviewsQuery ) );
|
||||
const isReviewsRequesting = isGetReviewsRequesting( reviewsQuery );
|
||||
|
||||
if ( ! isReviewsError && ! isReviewsRequesting ) {
|
||||
numberOfReviews = totalReviews;
|
||||
unreadReviews =
|
||||
reviews.length &&
|
||||
reviews[ 0 ].date_created_gmt &&
|
||||
new Date( reviews[ 0 ].date_created_gmt + 'Z' ).getTime() >
|
||||
userData.activity_panel_reviews_last_read;
|
||||
}
|
||||
}
|
||||
|
||||
return { unreadNotes, unreadOrders, unreadReviews, numberOfReviews };
|
||||
} )( clickOutside( ActivityPanel ) );
|
||||
|
|
|
@ -7,8 +7,10 @@ import { Component, Fragment } from '@wordpress/element';
|
|||
import { compose } from '@wordpress/compose';
|
||||
import Gridicon from 'gridicons';
|
||||
import interpolateComponents from 'interpolate-components';
|
||||
import moment from 'moment';
|
||||
import { noop, isNull } from 'lodash';
|
||||
import PropTypes from 'prop-types';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
|
@ -33,7 +35,21 @@ import sanitizeHTML from 'lib/sanitize-html';
|
|||
import withSelect from 'wc-api/with-select';
|
||||
|
||||
class ReviewsPanel extends Component {
|
||||
renderReview( review ) {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.mountTime = new Date().getTime();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
const userDataFields = {
|
||||
[ 'activity_panel_reviews_last_read' ]: this.mountTime,
|
||||
};
|
||||
this.props.updateCurrentUserData( userDataFields );
|
||||
}
|
||||
|
||||
renderReview( review, props ) {
|
||||
const { lastRead } = props;
|
||||
const product =
|
||||
( review && review._embedded && review._embedded.up && review._embedded.up[ 0 ] ) || null;
|
||||
|
||||
|
@ -109,15 +125,40 @@ class ReviewsPanel extends Component {
|
|||
key={ review.id }
|
||||
title={ title }
|
||||
subtitle={ subtitle }
|
||||
date={ review.date_created }
|
||||
date={
|
||||
review.date_created_gmt
|
||||
? moment( review.date_created_gmt + 'Z' ).format( 'YYYY-MM-DDTH:mm:ss' )
|
||||
: null
|
||||
}
|
||||
icon={ icon }
|
||||
actions={ cardActions() }
|
||||
unread={
|
||||
! lastRead ||
|
||||
! review.date_created_gmt ||
|
||||
new Date( review.date_created_gmt + 'Z' ).getTime() > lastRead
|
||||
}
|
||||
>
|
||||
<span dangerouslySetInnerHTML={ sanitizeHTML( review.review ) } />
|
||||
</ActivityCard>
|
||||
);
|
||||
}
|
||||
|
||||
renderPlaceholders() {
|
||||
const { numberOfReviews } = this.props;
|
||||
const placeholders = new Array( numberOfReviews );
|
||||
return placeholders
|
||||
.fill( 0 )
|
||||
.map( ( p, i ) => (
|
||||
<ActivityCardPlaceholder
|
||||
className="woocommerce-review-activity-card"
|
||||
key={ i }
|
||||
hasAction
|
||||
hasDate
|
||||
lines={ 2 }
|
||||
/>
|
||||
) );
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isError, isRequesting, reviews } = this.props;
|
||||
|
||||
|
@ -148,14 +189,11 @@ class ReviewsPanel extends Component {
|
|||
<ActivityHeader title={ __( 'Reviews', 'woocommerce-admin' ) } />
|
||||
<Section>
|
||||
{ isRequesting ? (
|
||||
<ActivityCardPlaceholder
|
||||
className="woocommerce-review-activity-card"
|
||||
hasAction
|
||||
hasDate
|
||||
lines={ 2 }
|
||||
/>
|
||||
this.renderPlaceholders()
|
||||
) : (
|
||||
<Fragment>{ reviews.map( this.renderReview ) }</Fragment>
|
||||
<Fragment>
|
||||
{ reviews.map( review => this.renderReview( review, this.props ) ) }
|
||||
</Fragment>
|
||||
) }
|
||||
</Section>
|
||||
</Fragment>
|
||||
|
@ -167,17 +205,26 @@ ReviewsPanel.propTypes = {
|
|||
reviews: PropTypes.array.isRequired,
|
||||
isError: PropTypes.bool,
|
||||
isRequesting: PropTypes.bool,
|
||||
numberOfReviews: PropTypes.number,
|
||||
};
|
||||
|
||||
ReviewsPanel.defaultProps = {
|
||||
reviews: [],
|
||||
isError: false,
|
||||
isRequesting: false,
|
||||
numberOfReviews: 0,
|
||||
};
|
||||
|
||||
export default compose(
|
||||
withSelect( select => {
|
||||
const { getReviews, getReviewsError, isGetReviewsRequesting } = select( 'wc-api' );
|
||||
withSelect( ( select, props ) => {
|
||||
const { numberOfReviews } = props;
|
||||
const { getCurrentUserData, getReviews, getReviewsError, isGetReviewsRequesting } = select(
|
||||
'wc-api'
|
||||
);
|
||||
if ( numberOfReviews === 0 ) {
|
||||
return {};
|
||||
}
|
||||
const userData = getCurrentUserData();
|
||||
const reviewsQuery = {
|
||||
page: 1,
|
||||
per_page: QUERY_DEFAULTS.pageSize,
|
||||
|
@ -188,6 +235,13 @@ export default compose(
|
|||
const isError = Boolean( getReviewsError( reviewsQuery ) );
|
||||
const isRequesting = isGetReviewsRequesting( reviewsQuery );
|
||||
|
||||
return { reviews, isError, isRequesting };
|
||||
return { reviews, isError, isRequesting, lastRead: userData.activity_panel_reviews_last_read };
|
||||
} ),
|
||||
withDispatch( dispatch => {
|
||||
const { updateCurrentUserData } = dispatch( 'wc-api' );
|
||||
|
||||
return {
|
||||
updateCurrentUserData,
|
||||
};
|
||||
} )
|
||||
)( ReviewsPanel );
|
||||
|
|
|
@ -47,6 +47,7 @@ function updateCurrentUserData( resourceNames, data, fetch ) {
|
|||
'dashboard_leaderboards',
|
||||
'dashboard_leaderboard_rows',
|
||||
'activity_panel_inbox_last_read',
|
||||
'activity_panel_reviews_last_read',
|
||||
];
|
||||
|
||||
if ( resourceNames.includes( resourceName ) ) {
|
||||
|
|
|
@ -450,6 +450,7 @@ function wc_admin_get_user_data_fields() {
|
|||
'dashboard_leaderboards',
|
||||
'dashboard_leaderboard_rows',
|
||||
'activity_panel_inbox_last_read',
|
||||
'activity_panel_reviews_last_read',
|
||||
);
|
||||
|
||||
return apply_filters( 'wc_admin_get_user_data_fields', $user_data_fields );
|
||||
|
|
Loading…
Reference in New Issue