woocommerce/plugins/woocommerce-admin/client/marketing/components/knowledge-base/index.js

260 lines
5.8 KiB
JavaScript
Raw Normal View History

/**
* External dependencies
*/
import { compose } from '@wordpress/compose';
import { __ } from '@wordpress/i18n';
import classNames from 'classnames';
import { withDispatch, withSelect } from '@wordpress/data';
import { useState } from '@wordpress/element';
import PropTypes from 'prop-types';
Convert the marketing tab cards to use the new @wordpress/components Card component. (https://github.com/woocommerce/woocommerce-admin/pull/5428) * Change WooCommerce Card to WordPress Card in the WelcomeCard component. Use isElevated and margin-bottom to make the Card look close to previous UI. * Use WordPress Card in KnowledgeBase. For the description in Card header, it will be rendered as a p element instead of h2, which should be more semantically correct. Test is updated to reflect this. * Add Card component wrapper that supports title and description props. * Use WordPress Card component wrapper in recommended extensions. * Code refactor to use WordPress Card wrapper. * Use WordPress Card wrapper in installed extension. * Use margin-bottom for children layout at the parent CSS level. * Add test for Card. * Fix no margin between cards in Coupons page, and remove previous css for WooCommerce Card. * Remove old WooCommerce Card css. * Don't use isElevated in Card, to match the style in WooCommerce Home screen. * Make item border color consistent with WordPress Card in Installed Extension card. Use WordPress Card without CardBody here because we don't want the padding from CardBody. * Make the card description look similar to previous WooCommerce Card description. * Fix spelling in CSS class names. * Fix WooCommerce spelling in comment. * Change the Marketing Card style to match with WooCommerce Home style. Also change the text gray color to use CSS variable instead of hardcoded gray value. Also remove the usage of h2 in the Card header to follow WooCommerce Home style. * Use $gray-200 as light borders between items in card. * Remove unneeded CSS code based on TODO in comment.
2020-10-23 06:41:45 +00:00
import { Pagination, EmptyContent } from '@woocommerce/components';
import { recordEvent } from '@woocommerce/tracks';
/**
* Internal dependencies
*/
import './style.scss';
import { Slider } from '../../components';
import { STORE_KEY } from '../../data/constants';
Convert the marketing tab cards to use the new @wordpress/components Card component. (https://github.com/woocommerce/woocommerce-admin/pull/5428) * Change WooCommerce Card to WordPress Card in the WelcomeCard component. Use isElevated and margin-bottom to make the Card look close to previous UI. * Use WordPress Card in KnowledgeBase. For the description in Card header, it will be rendered as a p element instead of h2, which should be more semantically correct. Test is updated to reflect this. * Add Card component wrapper that supports title and description props. * Use WordPress Card component wrapper in recommended extensions. * Code refactor to use WordPress Card wrapper. * Use WordPress Card wrapper in installed extension. * Use margin-bottom for children layout at the parent CSS level. * Add test for Card. * Fix no margin between cards in Coupons page, and remove previous css for WooCommerce Card. * Remove old WooCommerce Card css. * Don't use isElevated in Card, to match the style in WooCommerce Home screen. * Make item border color consistent with WordPress Card in Installed Extension card. Use WordPress Card without CardBody here because we don't want the padding from CardBody. * Make the card description look similar to previous WooCommerce Card description. * Fix spelling in CSS class names. * Fix WooCommerce spelling in comment. * Change the Marketing Card style to match with WooCommerce Home style. Also change the text gray color to use CSS variable instead of hardcoded gray value. Also remove the usage of h2 in the Card header to follow WooCommerce Home style. * Use $gray-200 as light borders between items in card. * Remove unneeded CSS code based on TODO in comment.
2020-10-23 06:41:45 +00:00
import Card from '../card';
import ReadBlogMessage from './ReadBlogMessage';
import KnowledgebaseCardPostPlaceholder from './placeholder';
const KnowledgeBase = ( {
posts,
isLoading,
error,
title,
description,
category,
} ) => {
const [ page, updatePage ] = useState( 1 );
const [ animate, updateAnimate ] = useState( null );
const onPaginationPageChange = ( newPage ) => {
let newAnimate;
if ( newPage > page ) {
newAnimate = 'left';
recordEvent( 'marketing_knowledge_carousel', {
direction: 'forward',
page: newPage,
} );
} else {
newAnimate = 'right';
recordEvent( 'marketing_knowledge_carousel', {
direction: 'back',
page: newPage,
} );
}
updatePage( newPage );
updateAnimate( newAnimate );
};
const onPostClick = ( post ) => {
recordEvent( 'marketing_knowledge_article', { title: post.title } );
};
/**
* Get the 2 posts we need for the current page
*/
const getCurrentSlide = () => {
const currentPosts = posts.slice(
( page - 1 ) * 2,
( page - 1 ) * 2 + 2
);
const pageClass = classNames(
'woocommerce-marketing-knowledgebase-card__page',
{
'page-with-single-post': currentPosts.length === 1,
}
);
const displayPosts = currentPosts.map( ( post, index ) => {
return (
<a
className="woocommerce-marketing-knowledgebase-card__post"
href={ post.link }
key={ index }
onClick={ () => {
onPostClick( post );
} }
target="_blank"
rel="noopener noreferrer"
>
{ post.image && (
<div className="woocommerce-marketing-knowledgebase-card__post-img">
<img src={ post.image } alt="" />
</div>
) }
<div className="woocommerce-marketing-knowledgebase-card__post-text">
<h3>{ post.title }</h3>
<p className="woocommerce-marketing-knowledgebase-card__post-meta">
{ __( 'By', 'woocommerce-admin' ) + ' ' }
{ post.author_name }
{ post.author_avatar && (
<img
src={ post.author_avatar.replace(
's=96',
's=32'
) }
className="woocommerce-gravatar"
alt=""
width="16"
height="16"
/>
) }
</p>
</div>
</a>
);
} );
return <div className={ pageClass }>{ displayPosts }</div>;
};
const renderEmpty = () => {
const emptyTitle = __( 'No posts yet', 'woocommerce-admin' );
return (
<EmptyContent
title={ emptyTitle }
message={ <ReadBlogMessage /> }
illustration=""
actionLabel=""
/>
);
};
const renderError = () => {
const errorTitle = __(
"Oops, our posts aren't loading right now",
'woocommerce-admin'
);
return (
<EmptyContent
title={ errorTitle }
message={ <ReadBlogMessage /> }
illustration=""
actionLabel=""
/>
);
};
const renderPosts = () => {
return (
<div className="woocommerce-marketing-knowledgebase-card__posts">
<Slider animationKey={ page } animate={ animate }>
{ getCurrentSlide() }
</Slider>
<Pagination
page={ page }
perPage={ 2 }
total={ posts.length }
onPageChange={ onPaginationPageChange }
showPagePicker={ false }
showPerPagePicker={ false }
showPageArrowsLabel={ false }
/>
</div>
);
};
/**
* Renders two `KnowledgebaseCardPostPlaceholder`s wrapped to mimic {@link renderPosts()} output.
*/
const renderPlaceholder = () => {
return (
<div className="woocommerce-marketing-knowledgebase-card__posts">
<div className="woocommerce-marketing-knowledgebase-card__page">
<KnowledgebaseCardPostPlaceholder />
<KnowledgebaseCardPostPlaceholder />
</div>
</div>
);
};
const renderCardBody = () => {
if ( isLoading ) {
return renderPlaceholder();
}
if ( error ) {
return renderError();
}
return posts.length === 0 ? renderEmpty() : renderPosts();
};
const categoryClass = category
? `woocommerce-marketing-knowledgebase-card__category-${ category }`
: '';
return (
<Card
title={ title }
description={ description }
className={ classNames(
'woocommerce-marketing-knowledgebase-card',
categoryClass
) }
>
{ renderCardBody() }
</Card>
);
};
KnowledgeBase.propTypes = {
/**
* Array of posts.
*/
posts: PropTypes.arrayOf( PropTypes.object ).isRequired,
/**
* Whether the card is loading.
*/
isLoading: PropTypes.bool.isRequired,
/**
* Cart title.
*/
title: PropTypes.string,
/**
* Card description.
*/
description: PropTypes.string,
/**
* Category of extensions to display.
*/
category: PropTypes.string,
};
KnowledgeBase.defaultProps = {
title: __( 'WooCommerce knowledge base', 'woocommerce-admin' ),
description: __(
'Learn the ins and outs of successful marketing from the experts at WooCommerce.',
'woocommerce-admin'
),
};
export { KnowledgeBase };
export default compose(
withSelect( ( select, props ) => {
const { getBlogPosts, getBlogPostsError, isResolving } = select(
STORE_KEY
);
return {
posts: getBlogPosts( props.category ),
isLoading: isResolving( 'getBlogPosts', [ props.category ] ),
error: getBlogPostsError( props.category ),
};
} ),
withDispatch( ( dispatch ) => {
const { createNotice } = dispatch( 'core/notices' );
return {
createNotice,
};
} )
)( KnowledgeBase );