woocommerce/plugins/woocommerce-admin/client/task-list/index.js

446 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { Component, cloneElement, Fragment } from '@wordpress/element';
import { get, isEqual } from 'lodash';
import { compose } from '@wordpress/compose';
import classNames from 'classnames';
import {
Button,
Card,
CardBody,
CardHeader,
Modal,
} from '@wordpress/components';
import { withDispatch } from '@wordpress/data';
import { Icon, check, chevronRight } from '@wordpress/icons';
/**
* WooCommerce dependencies
*/
import { H, List, EllipsisMenu } from '@woocommerce/components';
import { updateQueryString } from '@woocommerce/navigation';
import { ONBOARDING_STORE_NAME, PLUGINS_STORE_NAME } from '@woocommerce/data';
/**
* Internal dependencies
*/
import './style.scss';
import CartModal from 'dashboard/components/cart-modal';
import { getAllTasks } from './tasks';
import { recordEvent } from 'lib/tracks';
import withSelect from 'wc-api/with-select';
class TaskDashboard extends Component {
constructor( props ) {
super( props );
this.state = {
isCartModalOpen: false,
isWelcomeModalOpen: ! props.modalDismissed,
};
}
componentDidMount() {
const { incompleteTasks, updateOptions } = this.props;
document.body.classList.add( 'woocommerce-onboarding' );
document.body.classList.add( 'woocommerce-task-dashboard__body' );
this.recordTaskView();
this.recordTaskListView();
if ( ! incompleteTasks.length ) {
updateOptions( {
woocommerce_task_list_complete: 'yes',
} );
}
this.possiblyTrackCompletedTasks();
}
componentDidUpdate( prevProps ) {
const {
completedTaskKeys,
incompleteTasks,
query,
updateOptions,
} = this.props;
const {
completedTaskKeys: prevCompletedTaskKeys,
incompleteTasks: prevIncompleteTasks,
query: prevQuery,
} = prevProps;
const { task: prevTask } = prevQuery;
const { task } = query;
if ( prevTask !== task ) {
window.document.documentElement.scrollTop = 0;
this.recordTaskView();
}
if ( ! incompleteTasks.length && prevIncompleteTasks.length ) {
updateOptions( {
woocommerce_task_list_complete: 'yes',
} );
}
if ( ! isEqual( prevCompletedTaskKeys, completedTaskKeys ) ) {
this.possiblyTrackCompletedTasks();
}
}
possiblyTrackCompletedTasks() {
const {
completedTaskKeys,
trackedCompletedTasks,
updateOptions,
} = this.props;
if ( ! isEqual( trackedCompletedTasks, completedTaskKeys ) ) {
updateOptions( {
woocommerce_task_list_tracked_completed_tasks: completedTaskKeys,
} );
}
}
componentWillUnmount() {
document.body.classList.remove( 'woocommerce-onboarding' );
document.body.classList.remove( 'woocommerce-task-dashboard__body' );
}
getTasks() {
const {
profileItems,
query,
taskListPayments,
installedPlugins,
} = this.props;
return getAllTasks( {
profileItems,
options: taskListPayments,
query,
toggleCartModal: this.toggleCartModal.bind( this ),
installedPlugins,
} ).filter( ( task ) => task.visible );
}
getPluginsInformation() {
const {
isJetpackConnected,
activePlugins,
installedPlugins,
} = this.props;
return {
wcs_installed: installedPlugins.includes( 'woocommerce-services' ),
wcs_active: activePlugins.includes( 'woocommerce-services' ),
jetpack_installed: installedPlugins.includes( 'jetpack' ),
jetpack_active: activePlugins.includes( 'jetpack' ),
jetpack_connected: isJetpackConnected,
};
}
recordTaskView() {
const { task } = this.props.query;
// eslint-disable-next-line @wordpress/no-unused-vars-before-return
const pluginsInformation = this.getPluginsInformation();
if ( ! task ) {
return;
}
recordEvent( 'task_view', {
task_name: task,
...pluginsInformation,
} );
}
recordTaskListView() {
if ( this.getCurrentTask() ) {
return;
}
const { profileItems } = this.props;
const tasks = this.getTasks();
recordEvent( 'tasklist_view', {
number_tasks: tasks.length,
store_connected: profileItems.wccom_connected,
} );
}
keepTaskCard() {
recordEvent( 'tasklist_completed', {
action: 'keep_card',
} );
this.props.updateOptions( {
woocommerce_task_list_prompt_shown: true,
} );
}
hideTaskCard( action ) {
recordEvent( 'tasklist_completed', {
action,
} );
this.props.updateOptions( {
woocommerce_task_list_hidden: 'yes',
woocommerce_task_list_prompt_shown: true,
} );
}
getCurrentTask() {
const { task } = this.props.query;
const currentTask = this.getTasks().find( ( s ) => s.key === task );
if ( ! currentTask ) {
return null;
}
return currentTask;
}
renderMenu() {
return (
<div className="woocommerce-card__menu woocommerce-card__header-item">
<EllipsisMenu
label={ __( 'Task List Options', 'woocommerce-admin' ) }
renderContent={ () => (
<div className="woocommerce-task-card__section-controls">
<Button
onClick={ () =>
this.hideTaskCard( 'remove_card' )
}
>
{ __( 'Hide this', 'woocommerce-admin' ) }
</Button>
</div>
) }
/>
</div>
);
}
toggleCartModal() {
const { isCartModalOpen } = this.state;
if ( ! isCartModalOpen ) {
recordEvent( 'tasklist_purchase_extensions' );
}
this.setState( { isCartModalOpen: ! isCartModalOpen } );
}
closeWelcomeModal() {
// Prevent firing this event before the modal is seen.
if (
document.body.classList.contains( 'woocommerce-admin-is-loading' )
) {
return;
}
this.setState( { isWelcomeModalOpen: false } );
this.props.updateOptions( {
woocommerce_task_list_welcome_modal_dismissed: true,
} );
}
renderWelcomeModal() {
return (
<Modal
title={
<Fragment>
<span
role="img"
aria-hidden="true"
focusable="false"
className="woocommerce-task-dashboard__welcome-modal-icon"
>
🚀
</span>
{ __(
"Woo hoo - you're almost there!",
'woocommerce-admin'
) }
</Fragment>
}
onRequestClose={ () => this.closeWelcomeModal() }
className="woocommerce-task-dashboard__welcome-modal"
>
<div className="woocommerce-task-dashboard__welcome-modal-wrapper">
<div className="woocommerce-task-dashboard__welcome-modal-message">
<p>
{ __(
'Based on the information you provided weve prepared some final set up tasks for you to perform.',
'woocommerce-admin'
) }
</p>
<p>
{ __(
'Once complete your store will be ready for launch - exciting!',
'woocommerce-admin'
) }
</p>
</div>
<Button
isPrimary
isDefault
onClick={ () => this.closeWelcomeModal() }
>
{ __( 'Continue', 'woocommerce-admin' ) }
</Button>
</div>
</Modal>
);
}
render() {
const { query } = this.props;
const { isCartModalOpen, isWelcomeModalOpen } = this.state;
const currentTask = this.getCurrentTask();
const listTasks = this.getTasks().map( ( task ) => {
task.className = classNames(
task.completed ? 'is-complete' : null,
task.className
);
task.before = (
<div className="woocommerce-task__icon">
{ task.completed && <Icon icon={ check } /> }
</div>
);
if ( ! task.completed ) {
task.after = task.time ? (
<span className="woocommerce-task-estimated-time">
{ task.time }
</span>
) : (
<Icon icon={ chevronRight } />
);
}
if ( ! task.onClick ) {
task.onClick = () => updateQueryString( { task: task.key } );
}
return task;
} );
const numCompleteTasks = listTasks.filter( ( task ) => task.completed )
.length;
const progressBarClass = classNames(
'woocommerce-task-card__progress-bar',
{
completed: listTasks.length === numCompleteTasks,
}
);
return (
<Fragment>
<div className="woocommerce-task-dashboard__container">
{ currentTask ? (
cloneElement( currentTask.container, {
query,
} )
) : (
<Fragment>
<Card
size="large"
className="woocommerce-task-card"
>
<progress
className={ progressBarClass }
max={ listTasks.length }
value={ numCompleteTasks }
/>
<CardHeader>
<H>
{ __(
'Finish setup',
'woocommerce-admin'
) }
</H>
{ this.renderMenu() }
</CardHeader>
<CardBody>
<List items={ listTasks } />
</CardBody>
</Card>
{ isWelcomeModalOpen && this.renderWelcomeModal() }
</Fragment>
) }
</div>
{ isCartModalOpen && (
<CartModal
onClose={ () => this.toggleCartModal() }
onClickPurchaseLater={ () => this.toggleCartModal() }
/>
) }
</Fragment>
);
}
}
export default compose(
withSelect( ( select, props ) => {
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
const { getOptions } = select( 'wc-api' );
const {
getActivePlugins,
getInstalledPlugins,
isJetpackConnected,
} = select( PLUGINS_STORE_NAME );
const profileItems = getProfileItems();
const options = getOptions( [
'woocommerce_task_list_welcome_modal_dismissed',
'woocommerce_task_list_hidden',
'woocommerce_task_list_tracked_completed_tasks',
] );
const modalDismissed = get(
options,
[ 'woocommerce_task_list_welcome_modal_dismissed' ],
false
);
const taskListPayments = getOptions( [
'woocommerce_task_list_payments',
] );
const trackedCompletedTasks = get(
options,
[ 'woocommerce_task_list_tracked_completed_tasks' ],
[]
);
const installedPlugins = getInstalledPlugins();
const tasks = getAllTasks( {
profileItems,
options: getOptions( [ 'woocommerce_task_list_payments' ] ),
query: props.query,
installedPlugins,
} );
const completedTaskKeys = tasks
.filter( ( task ) => task.completed )
.map( ( task ) => task.key );
const incompleteTasks = tasks.filter(
( task ) => task.visible && ! task.completed
);
const activePlugins = getActivePlugins();
return {
modalDismissed,
profileItems,
taskListPayments,
isJetpackConnected: isJetpackConnected(),
incompleteTasks,
trackedCompletedTasks,
completedTaskKeys,
activePlugins,
installedPlugins,
};
} ),
withDispatch( ( dispatch ) => {
const { updateOptions } = dispatch( 'wc-api' );
return {
updateOptions,
};
} )
)( TaskDashboard );