Update task list component to make use of new experimental list (https://github.com/woocommerce/woocommerce-admin/pull/6849)
* Add initial task item component with the new task list * Switch components to functional components * Some minor updates from the last rebase * Fix missing variables. * Fix tests * Add animation for the experimental list * Fix lint error * Add changelog * Fix E2E tests * Update PR suggestions and export list from experimental package * Fix dismiss styling issue Co-authored-by: Jeff Stieler <jeff.m.stieler@gmail.com>
This commit is contained in:
parent
93e78028a0
commit
071a68b950
|
@ -3,10 +3,9 @@
|
|||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { MenuGroup, MenuItem } from '@wordpress/components';
|
||||
import { Component } from '@wordpress/element';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
import { check } from '@wordpress/icons';
|
||||
import { useState, useEffect } from '@wordpress/element';
|
||||
import { useDispatch, useSelect } from '@wordpress/data';
|
||||
import {
|
||||
ONBOARDING_STORE_NAME,
|
||||
OPTIONS_STORE_NAME,
|
||||
|
@ -24,25 +23,78 @@ import { getAllTasks } from './tasks';
|
|||
import { getCountryCode } from '../dashboard/utils';
|
||||
import TaskList from './list';
|
||||
import { DisplayOption } from '../header/activity-panel/display-options';
|
||||
import { TaskStep } from './task-step';
|
||||
|
||||
export class TaskDashboard extends Component {
|
||||
constructor( props ) {
|
||||
super( props );
|
||||
this.state = {
|
||||
isCartModalOpen: false,
|
||||
};
|
||||
const taskDashboardSelect = ( select ) => {
|
||||
const { getProfileItems, getTasksStatus } = select( ONBOARDING_STORE_NAME );
|
||||
const { getSettings } = select( SETTINGS_STORE_NAME );
|
||||
const { getOption } = select( OPTIONS_STORE_NAME );
|
||||
const {
|
||||
getActivePlugins,
|
||||
getInstalledPlugins,
|
||||
isJetpackConnected,
|
||||
} = select( PLUGINS_STORE_NAME );
|
||||
const profileItems = getProfileItems();
|
||||
|
||||
this.toggleExtensionTaskList = this.toggleExtensionTaskList.bind(
|
||||
this
|
||||
);
|
||||
}
|
||||
componentDidMount() {
|
||||
const trackedCompletedTasks =
|
||||
getOption( 'woocommerce_task_list_tracked_completed_tasks' ) || [];
|
||||
|
||||
const { general: generalSettings = {} } = getSettings( 'general' );
|
||||
const countryCode = getCountryCode(
|
||||
generalSettings.woocommerce_default_country
|
||||
);
|
||||
|
||||
const activePlugins = getActivePlugins();
|
||||
const installedPlugins = getInstalledPlugins();
|
||||
const onboardingStatus = getTasksStatus();
|
||||
|
||||
return {
|
||||
activePlugins,
|
||||
countryCode,
|
||||
dismissedTasks: getOption( 'woocommerce_task_list_dismissed_tasks' ),
|
||||
isExtendedTaskListComplete:
|
||||
getOption( 'woocommerce_extended_task_list_complete' ) === 'yes',
|
||||
isExtendedTaskListHidden:
|
||||
getOption( 'woocommerce_extended_task_list_hidden' ) === 'yes',
|
||||
isJetpackConnected: isJetpackConnected(),
|
||||
isSetupTaskListHidden:
|
||||
getOption( 'woocommerce_task_list_hidden' ) === 'yes',
|
||||
isTaskListComplete:
|
||||
getOption( 'woocommerce_task_list_complete' ) === 'yes',
|
||||
installedPlugins,
|
||||
onboardingStatus,
|
||||
profileItems,
|
||||
trackedCompletedTasks,
|
||||
};
|
||||
};
|
||||
|
||||
const TaskDashboard = ( { userPreferences, query } ) => {
|
||||
const { createNotice } = useDispatch( 'core/notices' );
|
||||
const { updateOptions } = useDispatch( OPTIONS_STORE_NAME );
|
||||
const { installAndActivatePlugins } = useDispatch( PLUGINS_STORE_NAME );
|
||||
const {
|
||||
trackedCompletedTasks,
|
||||
activePlugins,
|
||||
countryCode,
|
||||
installedPlugins,
|
||||
isJetpackConnected,
|
||||
onboardingStatus,
|
||||
profileItems,
|
||||
isSetupTaskListHidden,
|
||||
dismissedTasks,
|
||||
isTaskListComplete,
|
||||
isExtendedTaskListHidden,
|
||||
isExtendedTaskListComplete,
|
||||
} = useSelect( taskDashboardSelect );
|
||||
|
||||
const [ isCartModalOpen, setIsCartModalOpen ] = useState( false );
|
||||
|
||||
useEffect( () => {
|
||||
document.body.classList.add( 'woocommerce-onboarding' );
|
||||
document.body.classList.add( 'woocommerce-task-dashboard__body' );
|
||||
}
|
||||
}, [] );
|
||||
|
||||
getTaskStartedCount = ( taskName ) => {
|
||||
const { userPreferences } = this.props;
|
||||
const getTaskStartedCount = ( taskName ) => {
|
||||
const trackedStartedTasks =
|
||||
userPreferences.task_list_tracked_started_tasks;
|
||||
if ( ! trackedStartedTasks || ! trackedStartedTasks[ taskName ] ) {
|
||||
|
@ -51,8 +103,7 @@ export class TaskDashboard extends Component {
|
|||
return trackedStartedTasks[ taskName ];
|
||||
};
|
||||
|
||||
updateTrackStartedCount = ( taskName, newCount ) => {
|
||||
const { userPreferences } = this.props;
|
||||
const updateTrackStartedCount = ( taskName, newCount ) => {
|
||||
const trackedStartedTasks =
|
||||
userPreferences.task_list_tracked_started_tasks || {};
|
||||
userPreferences.updateUserPreferences( {
|
||||
|
@ -63,26 +114,24 @@ export class TaskDashboard extends Component {
|
|||
} );
|
||||
};
|
||||
|
||||
isTaskCompleted = ( taskName ) => {
|
||||
const { trackedCompletedTasks } = this.props;
|
||||
const isTaskCompleted = ( taskName ) => {
|
||||
if ( ! trackedCompletedTasks ) {
|
||||
return false;
|
||||
}
|
||||
return trackedCompletedTasks.includes( taskName );
|
||||
};
|
||||
|
||||
onTaskSelect = ( taskName ) => {
|
||||
const trackStartedCount = this.getTaskStartedCount( taskName );
|
||||
const onTaskSelect = ( taskName ) => {
|
||||
const trackStartedCount = getTaskStartedCount( taskName );
|
||||
recordEvent( 'tasklist_click', {
|
||||
task_name: taskName,
|
||||
} );
|
||||
if ( ! this.isTaskCompleted( taskName ) ) {
|
||||
this.updateTrackStartedCount( taskName, trackStartedCount + 1 );
|
||||
if ( ! isTaskCompleted( taskName ) ) {
|
||||
updateTrackStartedCount( taskName, trackStartedCount + 1 );
|
||||
}
|
||||
};
|
||||
|
||||
toggleExtensionTaskList = () => {
|
||||
const { isExtendedTaskListHidden, updateOptions } = this.props;
|
||||
const toggleExtensionTaskList = () => {
|
||||
const newValue = ! isExtendedTaskListHidden;
|
||||
|
||||
recordEvent(
|
||||
|
@ -93,184 +142,121 @@ export class TaskDashboard extends Component {
|
|||
} );
|
||||
};
|
||||
|
||||
getAllTasks() {
|
||||
const {
|
||||
activePlugins,
|
||||
countryCode,
|
||||
createNotice,
|
||||
installAndActivatePlugins,
|
||||
installedPlugins,
|
||||
isJetpackConnected,
|
||||
onboardingStatus,
|
||||
profileItems,
|
||||
query,
|
||||
} = this.props;
|
||||
|
||||
return getAllTasks( {
|
||||
activePlugins,
|
||||
countryCode,
|
||||
createNotice,
|
||||
installAndActivatePlugins,
|
||||
installedPlugins,
|
||||
isJetpackConnected,
|
||||
onboardingStatus,
|
||||
profileItems,
|
||||
query,
|
||||
toggleCartModal: this.toggleCartModal.bind( this ),
|
||||
onTaskSelect: this.onTaskSelect,
|
||||
} );
|
||||
}
|
||||
|
||||
toggleCartModal() {
|
||||
const { isCartModalOpen } = this.state;
|
||||
|
||||
const toggleCartModal = () => {
|
||||
if ( ! isCartModalOpen ) {
|
||||
recordEvent( 'tasklist_purchase_extensions' );
|
||||
}
|
||||
|
||||
this.setState( { isCartModalOpen: ! isCartModalOpen } );
|
||||
}
|
||||
setIsCartModalOpen( ! isCartModalOpen );
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
dismissedTasks,
|
||||
isExtendedTaskListComplete,
|
||||
isExtendedTaskListHidden,
|
||||
isSetupTaskListHidden,
|
||||
isTaskListComplete,
|
||||
query,
|
||||
trackedCompletedTasks,
|
||||
} = this.props;
|
||||
const { isCartModalOpen } = this.state;
|
||||
const allTasks = this.getAllTasks();
|
||||
const { extension, setup: setupTasks } = allTasks;
|
||||
const getCurrentTask = ( tasks ) => {
|
||||
const { task } = query;
|
||||
const currentTask = tasks.find( ( s ) => s.key === task );
|
||||
|
||||
const extensionTasks =
|
||||
Array.isArray( extension ) &&
|
||||
extension.sort( ( a, b ) => {
|
||||
if ( Boolean( a.completed ) === Boolean( b.completed ) ) {
|
||||
return 0;
|
||||
}
|
||||
if ( ! currentTask ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return a.completed ? 1 : -1;
|
||||
} );
|
||||
return currentTask;
|
||||
};
|
||||
|
||||
const allTasks = getAllTasks( {
|
||||
activePlugins,
|
||||
countryCode,
|
||||
createNotice,
|
||||
installAndActivatePlugins,
|
||||
installedPlugins,
|
||||
isJetpackConnected,
|
||||
onboardingStatus,
|
||||
profileItems,
|
||||
query,
|
||||
toggleCartModal,
|
||||
onTaskSelect,
|
||||
} );
|
||||
|
||||
const { extension, setup: setupTasks } = allTasks;
|
||||
const { task } = query;
|
||||
|
||||
const extensionTasks =
|
||||
Array.isArray( extension ) &&
|
||||
extension.sort( ( a, b ) => {
|
||||
if ( Boolean( a.completed ) === Boolean( b.completed ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return a.completed ? 1 : -1;
|
||||
} );
|
||||
|
||||
const currentTask = getCurrentTask( [
|
||||
...( extensionTasks || [] ),
|
||||
...( setupTasks || [] ),
|
||||
] );
|
||||
|
||||
if ( task && ! currentTask ) {
|
||||
return null;
|
||||
}
|
||||
if ( currentTask ) {
|
||||
return (
|
||||
<>
|
||||
{ setupTasks && ( ! isSetupTaskListHidden || task ) && (
|
||||
<TaskList
|
||||
dismissedTasks={ dismissedTasks || [] }
|
||||
isComplete={ isTaskListComplete }
|
||||
query={ query }
|
||||
tasks={ setupTasks }
|
||||
title={ __(
|
||||
'Get ready to start selling',
|
||||
'woocommerce-admin'
|
||||
) }
|
||||
trackedCompletedTasks={ trackedCompletedTasks || [] }
|
||||
/>
|
||||
) }
|
||||
{ extensionTasks && (
|
||||
<DisplayOption>
|
||||
<MenuGroup
|
||||
className="woocommerce-layout__homescreen-display-options"
|
||||
label={ __( 'Display', 'woocommerce-admin' ) }
|
||||
>
|
||||
<MenuItem
|
||||
className="woocommerce-layout__homescreen-extension-tasklist-toggle"
|
||||
icon={ ! isExtendedTaskListHidden && check }
|
||||
isSelected={ ! isExtendedTaskListHidden }
|
||||
role="menuitemcheckbox"
|
||||
onClick={ this.toggleExtensionTaskList }
|
||||
>
|
||||
{ __(
|
||||
'Show things to do next',
|
||||
'woocommerce-admin'
|
||||
) }
|
||||
</MenuItem>
|
||||
</MenuGroup>
|
||||
</DisplayOption>
|
||||
) }
|
||||
{ extensionTasks && ! isExtendedTaskListHidden && (
|
||||
<TaskList
|
||||
dismissedTasks={ dismissedTasks || [] }
|
||||
isComplete={ isExtendedTaskListComplete }
|
||||
name={ 'extended_task_list' }
|
||||
query={ query }
|
||||
tasks={ extensionTasks }
|
||||
title={ __( 'Things to do next', 'woocommerce-admin' ) }
|
||||
trackedCompletedTasks={ trackedCompletedTasks || [] }
|
||||
/>
|
||||
) }
|
||||
{ isCartModalOpen && (
|
||||
<CartModal
|
||||
onClose={ () => this.toggleCartModal() }
|
||||
onClickPurchaseLater={ () => this.toggleCartModal() }
|
||||
/>
|
||||
) }
|
||||
</>
|
||||
<TaskStep taskContainer={ currentTask.container } query={ query } />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getProfileItems, getTasksStatus } = select(
|
||||
ONBOARDING_STORE_NAME
|
||||
);
|
||||
const { getSettings } = select( SETTINGS_STORE_NAME );
|
||||
const { getOption } = select( OPTIONS_STORE_NAME );
|
||||
const {
|
||||
getActivePlugins,
|
||||
getInstalledPlugins,
|
||||
isJetpackConnected,
|
||||
} = select( PLUGINS_STORE_NAME );
|
||||
const profileItems = getProfileItems();
|
||||
return (
|
||||
<>
|
||||
{ setupTasks && ( ! isSetupTaskListHidden || task ) && (
|
||||
<TaskList
|
||||
dismissedTasks={ dismissedTasks || [] }
|
||||
isComplete={ isTaskListComplete }
|
||||
query={ query }
|
||||
tasks={ setupTasks }
|
||||
title={ __(
|
||||
'Get ready to start selling',
|
||||
'woocommerce-admin'
|
||||
) }
|
||||
trackedCompletedTasks={ trackedCompletedTasks || [] }
|
||||
/>
|
||||
) }
|
||||
{ extensionTasks && (
|
||||
<DisplayOption>
|
||||
<MenuGroup
|
||||
className="woocommerce-layout__homescreen-display-options"
|
||||
label={ __( 'Display', 'woocommerce-admin' ) }
|
||||
>
|
||||
<MenuItem
|
||||
className="woocommerce-layout__homescreen-extension-tasklist-toggle"
|
||||
icon={ ! isExtendedTaskListHidden && check }
|
||||
isSelected={ ! isExtendedTaskListHidden }
|
||||
role="menuitemcheckbox"
|
||||
onClick={ toggleExtensionTaskList }
|
||||
>
|
||||
{ __(
|
||||
'Show things to do next',
|
||||
'woocommerce-admin'
|
||||
) }
|
||||
</MenuItem>
|
||||
</MenuGroup>
|
||||
</DisplayOption>
|
||||
) }
|
||||
{ extensionTasks && ! isExtendedTaskListHidden && (
|
||||
<TaskList
|
||||
dismissedTasks={ dismissedTasks || [] }
|
||||
isComplete={ isExtendedTaskListComplete }
|
||||
name={ 'extended_task_list' }
|
||||
query={ query }
|
||||
tasks={ extensionTasks }
|
||||
title={ __( 'Things to do next', 'woocommerce-admin' ) }
|
||||
trackedCompletedTasks={ trackedCompletedTasks || [] }
|
||||
/>
|
||||
) }
|
||||
{ isCartModalOpen && (
|
||||
<CartModal
|
||||
onClose={ () => toggleCartModal() }
|
||||
onClickPurchaseLater={ () => toggleCartModal() }
|
||||
/>
|
||||
) }
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const trackedCompletedTasks =
|
||||
getOption( 'woocommerce_task_list_tracked_completed_tasks' ) || [];
|
||||
|
||||
const { general: generalSettings = {} } = getSettings( 'general' );
|
||||
const countryCode = getCountryCode(
|
||||
generalSettings.woocommerce_default_country
|
||||
);
|
||||
|
||||
const activePlugins = getActivePlugins();
|
||||
const installedPlugins = getInstalledPlugins();
|
||||
const onboardingStatus = getTasksStatus();
|
||||
|
||||
return {
|
||||
activePlugins,
|
||||
countryCode,
|
||||
dismissedTasks: getOption(
|
||||
'woocommerce_task_list_dismissed_tasks'
|
||||
),
|
||||
isExtendedTaskListComplete:
|
||||
getOption( 'woocommerce_extended_task_list_complete' ) ===
|
||||
'yes',
|
||||
isExtendedTaskListHidden:
|
||||
getOption( 'woocommerce_extended_task_list_hidden' ) === 'yes',
|
||||
isJetpackConnected: isJetpackConnected(),
|
||||
isSetupTaskListHidden:
|
||||
getOption( 'woocommerce_task_list_hidden' ) === 'yes',
|
||||
isTaskListComplete:
|
||||
getOption( 'woocommerce_task_list_complete' ) === 'yes',
|
||||
installedPlugins,
|
||||
onboardingStatus,
|
||||
profileItems,
|
||||
trackedCompletedTasks,
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
const { installAndActivatePlugins } = dispatch( PLUGINS_STORE_NAME );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
|
||||
return {
|
||||
createNotice,
|
||||
installAndActivatePlugins,
|
||||
updateOptions,
|
||||
};
|
||||
} )
|
||||
)( TaskDashboard );
|
||||
export default TaskDashboard;
|
||||
|
|
|
@ -2,55 +2,62 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Component, cloneElement } from '@wordpress/element';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import classNames from 'classnames';
|
||||
import { useEffect, useRef } from '@wordpress/element';
|
||||
import { Button, Card, CardBody, CardHeader } from '@wordpress/components';
|
||||
import { withDispatch, withSelect } from '@wordpress/data';
|
||||
import { Icon, check } from '@wordpress/icons';
|
||||
import { List, EllipsisMenu, Badge } from '@woocommerce/components';
|
||||
import { updateQueryString } from '@woocommerce/navigation';
|
||||
import { useSelect, useDispatch } from '@wordpress/data';
|
||||
import {
|
||||
PLUGINS_STORE_NAME,
|
||||
OPTIONS_STORE_NAME,
|
||||
ONBOARDING_STORE_NAME,
|
||||
SETTINGS_STORE_NAME,
|
||||
} from '@woocommerce/data';
|
||||
EllipsisMenu,
|
||||
Badge,
|
||||
__experimentalList as List,
|
||||
} from '@woocommerce/components';
|
||||
import { updateQueryString } from '@woocommerce/navigation';
|
||||
import { OPTIONS_STORE_NAME, ONBOARDING_STORE_NAME } from '@woocommerce/data';
|
||||
import { recordEvent } from '@woocommerce/tracks';
|
||||
import { Text } from '@woocommerce/experimental';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { recordTaskViewEvent } from './tasks';
|
||||
import { getCountryCode } from '../dashboard/utils';
|
||||
import sanitizeHTML from '../lib/sanitize-html';
|
||||
import { TaskItem } from './task-item';
|
||||
|
||||
export class TaskList extends Component {
|
||||
componentDidMount() {
|
||||
this.recordTaskView();
|
||||
this.recordTaskListView();
|
||||
this.possiblyCompleteTaskList();
|
||||
this.possiblyTrackCompletedTasks();
|
||||
}
|
||||
export const TaskList = ( {
|
||||
query,
|
||||
name = 'task_list',
|
||||
isComplete,
|
||||
dismissedTasks,
|
||||
tasks,
|
||||
trackedCompletedTasks: totalTrackedCompletedTasks,
|
||||
title: listTitle,
|
||||
} ) => {
|
||||
const { createNotice } = useDispatch( 'core/notices' );
|
||||
const { updateOptions } = useDispatch( OPTIONS_STORE_NAME );
|
||||
const { profileItems } = useSelect( ( select ) => {
|
||||
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
|
||||
|
||||
componentDidUpdate( prevProps ) {
|
||||
const { query } = this.props;
|
||||
const { query: prevQuery } = prevProps;
|
||||
const { task: prevTask } = prevQuery;
|
||||
return {
|
||||
profileItems: getProfileItems(),
|
||||
};
|
||||
} );
|
||||
|
||||
const prevQueryRef = useRef( query );
|
||||
useEffect( () => {
|
||||
recordTaskListView();
|
||||
}, [] );
|
||||
|
||||
useEffect( () => {
|
||||
const { task: prevTask } = prevQueryRef.current;
|
||||
const { task } = query;
|
||||
|
||||
if ( prevTask !== task ) {
|
||||
window.document.documentElement.scrollTop = 0;
|
||||
this.recordTaskView();
|
||||
prevQueryRef.current = query;
|
||||
}
|
||||
|
||||
this.possiblyCompleteTaskList();
|
||||
this.possiblyTrackCompletedTasks();
|
||||
}
|
||||
possiblyCompleteTaskList();
|
||||
possiblyTrackCompletedTasks();
|
||||
}, [ query ] );
|
||||
|
||||
possiblyCompleteTaskList() {
|
||||
const { isComplete, name = 'task_list', updateOptions } = this.props;
|
||||
const possiblyCompleteTaskList = () => {
|
||||
const taskListVariableName = `woocommerce_${ name }_complete`;
|
||||
const taskListToComplete = isComplete
|
||||
? { [ taskListVariableName ]: 'no' }
|
||||
|
@ -61,119 +68,78 @@ export class TaskList extends Component {
|
|||
}
|
||||
|
||||
if (
|
||||
( ! this.getIncompleteTasks().length && ! isComplete ) ||
|
||||
( this.getIncompleteTasks().length && isComplete )
|
||||
( ! getIncompleteTasks().length && ! isComplete ) ||
|
||||
( getIncompleteTasks().length && isComplete )
|
||||
) {
|
||||
updateOptions( {
|
||||
...taskListToComplete,
|
||||
} );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getCompletedTaskKeys() {
|
||||
return this.getVisibleTasks()
|
||||
const getCompletedTaskKeys = () => {
|
||||
return getVisibleTasks()
|
||||
.filter( ( task ) => task.completed )
|
||||
.map( ( task ) => task.key );
|
||||
}
|
||||
};
|
||||
|
||||
getIncompleteTasks() {
|
||||
const { dismissedTasks, tasks } = this.props;
|
||||
const getIncompleteTasks = () => {
|
||||
return tasks.filter(
|
||||
( task ) =>
|
||||
task.visible &&
|
||||
! task.completed &&
|
||||
! dismissedTasks.includes( task.key )
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
shouldUpdateCompletedTasks( tasks, untrackedTasks, completedTasks ) {
|
||||
if ( untrackedTasks.length > 0 ) {
|
||||
return true;
|
||||
}
|
||||
if ( completedTasks.length === 0 ) {
|
||||
return false;
|
||||
}
|
||||
return ! completedTasks.every(
|
||||
( taskName ) => tasks.indexOf( taskName ) >= 0
|
||||
);
|
||||
}
|
||||
|
||||
getTrackedCompletedTasks( completedTasks, trackedTasks ) {
|
||||
if ( ! trackedTasks ) {
|
||||
return [];
|
||||
}
|
||||
return completedTasks.filter( ( taskName ) =>
|
||||
trackedTasks.includes( taskName )
|
||||
);
|
||||
}
|
||||
|
||||
getTrackedIncompletedTasks( partialCompletedTasks, allTrackedTask ) {
|
||||
return this.getVisibleTasks()
|
||||
const getTrackedIncompletedTasks = (
|
||||
partialCompletedTasks,
|
||||
allTrackedTask
|
||||
) => {
|
||||
return getVisibleTasks()
|
||||
.filter(
|
||||
( task ) =>
|
||||
allTrackedTask.includes( task.key ) &&
|
||||
! partialCompletedTasks.includes( task.key )
|
||||
)
|
||||
.map( ( task ) => task.key );
|
||||
}
|
||||
};
|
||||
|
||||
getTasksForUpdate(
|
||||
completedTaskKeys,
|
||||
totalTrackedCompletedTasks,
|
||||
trackedIncompleteTasks
|
||||
) {
|
||||
const mergedLists = [
|
||||
...new Set( [
|
||||
...completedTaskKeys,
|
||||
...totalTrackedCompletedTasks,
|
||||
] ),
|
||||
];
|
||||
return mergedLists.filter(
|
||||
( taskName ) => ! trackedIncompleteTasks.includes( taskName )
|
||||
);
|
||||
}
|
||||
|
||||
possiblyTrackCompletedTasks() {
|
||||
const {
|
||||
trackedCompletedTasks: totalTrackedCompletedTasks,
|
||||
updateOptions,
|
||||
} = this.props;
|
||||
const completedTaskKeys = this.getCompletedTaskKeys();
|
||||
const trackedCompletedTasks = this.getTrackedCompletedTasks(
|
||||
const possiblyTrackCompletedTasks = () => {
|
||||
const completedTaskKeys = getCompletedTaskKeys();
|
||||
const trackedCompletedTasks = getTrackedCompletedTasks(
|
||||
completedTaskKeys,
|
||||
totalTrackedCompletedTasks
|
||||
);
|
||||
|
||||
const trackedIncompleteTasks = this.getTrackedIncompletedTasks(
|
||||
const trackedIncompleteTasks = getTrackedIncompletedTasks(
|
||||
trackedCompletedTasks,
|
||||
totalTrackedCompletedTasks
|
||||
);
|
||||
|
||||
if (
|
||||
this.shouldUpdateCompletedTasks(
|
||||
shouldUpdateCompletedTasks(
|
||||
trackedCompletedTasks,
|
||||
trackedIncompleteTasks,
|
||||
completedTaskKeys
|
||||
)
|
||||
) {
|
||||
updateOptions( {
|
||||
woocommerce_task_list_tracked_completed_tasks: this.getTasksForUpdate(
|
||||
woocommerce_task_list_tracked_completed_tasks: getTasksForUpdate(
|
||||
completedTaskKeys,
|
||||
totalTrackedCompletedTasks,
|
||||
trackedIncompleteTasks
|
||||
),
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
dismissTask( { key, onDismiss } ) {
|
||||
const { createNotice, dismissedTasks, updateOptions } = this.props;
|
||||
};
|
||||
|
||||
const dismissTask = ( { key, onDismiss } ) => {
|
||||
createNotice( 'success', __( 'Task dismissed' ), {
|
||||
actions: [
|
||||
{
|
||||
label: __( 'Undo', 'woocommerce-admin' ),
|
||||
onClick: () => this.undoDismissTask( key ),
|
||||
onClick: () => undoDismissTask( key ),
|
||||
},
|
||||
],
|
||||
} );
|
||||
|
@ -186,11 +152,9 @@ export class TaskList extends Component {
|
|||
if ( onDismiss ) {
|
||||
onDismiss();
|
||||
}
|
||||
}
|
||||
|
||||
undoDismissTask( key ) {
|
||||
const { dismissedTasks, updateOptions } = this.props;
|
||||
};
|
||||
|
||||
const undoDismissTask = ( key ) => {
|
||||
const updatedDismissedTasks = dismissedTasks.filter(
|
||||
( task ) => task !== key
|
||||
);
|
||||
|
@ -198,55 +162,31 @@ export class TaskList extends Component {
|
|||
updateOptions( {
|
||||
woocommerce_task_list_dismissed_tasks: updatedDismissedTasks,
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
getVisibleTasks() {
|
||||
const { dismissedTasks, tasks } = this.props;
|
||||
const getVisibleTasks = () => {
|
||||
return tasks.filter(
|
||||
( task ) => task.visible && ! dismissedTasks.includes( task.key )
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
recordTaskView() {
|
||||
const {
|
||||
isJetpackConnected,
|
||||
activePlugins,
|
||||
installedPlugins,
|
||||
query,
|
||||
} = this.props;
|
||||
const { task: taskName } = query;
|
||||
|
||||
if ( ! taskName ) {
|
||||
const recordTaskListView = () => {
|
||||
if ( query.task ) {
|
||||
return;
|
||||
}
|
||||
|
||||
recordTaskViewEvent(
|
||||
taskName,
|
||||
isJetpackConnected,
|
||||
activePlugins,
|
||||
installedPlugins
|
||||
);
|
||||
}
|
||||
|
||||
recordTaskListView() {
|
||||
if ( this.getCurrentTask() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { name = 'task_list', profileItems } = this.props;
|
||||
const isCoreTaskList = name === 'task_list';
|
||||
const taskListName = isCoreTaskList ? 'tasklist' : 'extended_tasklist';
|
||||
|
||||
const tasks = this.getVisibleTasks();
|
||||
const visibleTasks = getVisibleTasks();
|
||||
|
||||
recordEvent( `${ taskListName }_view`, {
|
||||
number_tasks: tasks.length,
|
||||
number_tasks: visibleTasks.length,
|
||||
store_connected: profileItems.wccom_connected,
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
hideTaskCard( action ) {
|
||||
const { name = 'task_list', updateOptions } = this.props;
|
||||
const hideTaskCard = ( action ) => {
|
||||
const isCoreTaskList = name === 'task_list';
|
||||
const taskListName = isCoreTaskList ? 'tasklist' : 'extended_tasklist';
|
||||
const updateOptionsParams = {
|
||||
|
@ -260,27 +200,15 @@ export class TaskList extends Component {
|
|||
|
||||
recordEvent( `${ taskListName }_completed`, {
|
||||
action,
|
||||
completed_task_count: this.getCompletedTaskKeys().length,
|
||||
incomplete_task_count: this.getIncompleteTasks().length,
|
||||
completed_task_count: getCompletedTaskKeys().length,
|
||||
incomplete_task_count: getIncompleteTasks().length,
|
||||
} );
|
||||
updateOptions( {
|
||||
...updateOptionsParams,
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
getCurrentTask() {
|
||||
const { query, tasks } = this.props;
|
||||
const { task } = query;
|
||||
const currentTask = tasks.find( ( s ) => s.key === task );
|
||||
|
||||
if ( ! currentTask ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return currentTask;
|
||||
}
|
||||
|
||||
renderMenu() {
|
||||
const renderMenu = () => {
|
||||
return (
|
||||
<div className="woocommerce-card__menu woocommerce-card__header-item">
|
||||
<EllipsisMenu
|
||||
|
@ -288,9 +216,7 @@ export class TaskList extends Component {
|
|||
renderContent={ () => (
|
||||
<div className="woocommerce-task-card__section-controls">
|
||||
<Button
|
||||
onClick={ () =>
|
||||
this.hideTaskCard( 'remove_card' )
|
||||
}
|
||||
onClick={ () => hideTaskCard( 'remove_card' ) }
|
||||
>
|
||||
{ __( 'Hide this', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
|
@ -299,162 +225,95 @@ export class TaskList extends Component {
|
|||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const { query, title: listTitle } = this.props;
|
||||
const { task: theTask } = query;
|
||||
const currentTask = this.getCurrentTask();
|
||||
const listTasks = getVisibleTasks().map( ( task ) => {
|
||||
if ( ! task.onClick ) {
|
||||
task.onClick = ( e ) => {
|
||||
if ( e.target.nodeName === 'A' ) {
|
||||
// This is a nested link, so don't activate this task.
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( theTask && ! currentTask ) {
|
||||
return null;
|
||||
updateQueryString( { task: task.key } );
|
||||
};
|
||||
}
|
||||
|
||||
const listTasks = this.getVisibleTasks().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>
|
||||
);
|
||||
return task;
|
||||
} );
|
||||
|
||||
task.title = (
|
||||
<Text
|
||||
as="div"
|
||||
variant={ task.completed ? 'body.small' : 'button' }
|
||||
if ( ! listTasks.length ) {
|
||||
return <div className="woocommerce-task-dashboard__container"></div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="woocommerce-task-dashboard__container">
|
||||
<Card
|
||||
size="large"
|
||||
className="woocommerce-task-card woocommerce-homescreen-card"
|
||||
>
|
||||
{ task.title }
|
||||
{ task.additionalInfo && (
|
||||
<div
|
||||
className="woocommerce-task__additional-info"
|
||||
dangerouslySetInnerHTML={ sanitizeHTML(
|
||||
task.additionalInfo
|
||||
) }
|
||||
></div>
|
||||
) }
|
||||
{ task.time && ! task.completed && (
|
||||
<div className="woocommerce-task__estimated-time">
|
||||
{ task.time }
|
||||
<CardHeader size="medium">
|
||||
<div className="wooocommerce-task-card__header">
|
||||
<Text variant="title.small">{ listTitle }</Text>
|
||||
<Badge count={ getIncompleteTasks().length } />
|
||||
</div>
|
||||
) }
|
||||
</Text>
|
||||
);
|
||||
{ renderMenu() }
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<List animation="slide-right">
|
||||
{ listTasks.map( ( task ) => (
|
||||
<TaskItem
|
||||
key={ task.key }
|
||||
title={ task.title }
|
||||
completed={ task.completed }
|
||||
content={ task.content }
|
||||
onClick={ task.onClick }
|
||||
isDismissable={ task.isDismissable }
|
||||
onDismiss={ () => dismissTask( task ) }
|
||||
time={ task.time }
|
||||
/>
|
||||
) ) }
|
||||
</List>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
if ( ! task.completed && task.isDismissable ) {
|
||||
task.after = (
|
||||
<Button
|
||||
data-testid={ `${ task.key }-dismiss-button` }
|
||||
isTertiary
|
||||
onClick={ ( event ) => {
|
||||
event.stopPropagation();
|
||||
this.dismissTask( task );
|
||||
} }
|
||||
>
|
||||
{ __( 'Dismiss', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! task.onClick ) {
|
||||
task.onClick = ( e ) => {
|
||||
if ( e.target.nodeName === 'A' ) {
|
||||
// This is a nested link, so don't activate this task.
|
||||
return false;
|
||||
}
|
||||
|
||||
updateQueryString( { task: task.key } );
|
||||
};
|
||||
}
|
||||
|
||||
return task;
|
||||
} );
|
||||
|
||||
if ( ! listTasks.length ) {
|
||||
return (
|
||||
<div className="woocommerce-task-dashboard__container"></div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="woocommerce-task-dashboard__container">
|
||||
{ currentTask ? (
|
||||
cloneElement( currentTask.container, {
|
||||
query,
|
||||
} )
|
||||
) : (
|
||||
<>
|
||||
<Card
|
||||
size="large"
|
||||
className="woocommerce-task-card woocommerce-homescreen-card"
|
||||
>
|
||||
<CardHeader size="medium">
|
||||
<div className="wooocommerce-task-card__header">
|
||||
<Text variant="title.small">
|
||||
{ listTitle }
|
||||
</Text>
|
||||
<Badge
|
||||
count={
|
||||
this.getIncompleteTasks().length
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
{ this.renderMenu() }
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<List items={ listTasks } />
|
||||
</CardBody>
|
||||
</Card>
|
||||
</>
|
||||
) }
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
function shouldUpdateCompletedTasks( tasks, untrackedTasks, completedTasks ) {
|
||||
if ( untrackedTasks.length > 0 ) {
|
||||
return true;
|
||||
}
|
||||
if ( completedTasks.length === 0 ) {
|
||||
return false;
|
||||
}
|
||||
return ! completedTasks.every(
|
||||
( taskName ) => tasks.indexOf( taskName ) >= 0
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getProfileItems, getTasksStatus } = select(
|
||||
ONBOARDING_STORE_NAME
|
||||
);
|
||||
const { getSettings } = select( SETTINGS_STORE_NAME );
|
||||
const {
|
||||
getActivePlugins,
|
||||
getInstalledPlugins,
|
||||
isJetpackConnected,
|
||||
} = select( PLUGINS_STORE_NAME );
|
||||
const profileItems = getProfileItems();
|
||||
const { general: generalSettings = {} } = getSettings( 'general' );
|
||||
const countryCode = getCountryCode(
|
||||
generalSettings.woocommerce_default_country
|
||||
);
|
||||
function getTrackedCompletedTasks( completedTasks, trackedTasks ) {
|
||||
if ( ! trackedTasks ) {
|
||||
return [];
|
||||
}
|
||||
return completedTasks.filter( ( taskName ) =>
|
||||
trackedTasks.includes( taskName )
|
||||
);
|
||||
}
|
||||
|
||||
const activePlugins = getActivePlugins();
|
||||
const installedPlugins = getInstalledPlugins();
|
||||
const onboardingStatus = getTasksStatus();
|
||||
function getTasksForUpdate(
|
||||
completedTaskKeys,
|
||||
totalTrackedCompletedTasks,
|
||||
trackedIncompleteTasks
|
||||
) {
|
||||
const mergedLists = [
|
||||
...new Set( [ ...completedTaskKeys, ...totalTrackedCompletedTasks ] ),
|
||||
];
|
||||
return mergedLists.filter(
|
||||
( taskName ) => ! trackedIncompleteTasks.includes( taskName )
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
activePlugins,
|
||||
countryCode,
|
||||
isJetpackConnected: isJetpackConnected(),
|
||||
installedPlugins,
|
||||
onboardingStatus,
|
||||
profileItems,
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
const { updateOptions } = dispatch( OPTIONS_STORE_NAME );
|
||||
const { installAndActivatePlugins } = dispatch( PLUGINS_STORE_NAME );
|
||||
|
||||
return {
|
||||
createNotice,
|
||||
installAndActivatePlugins,
|
||||
updateOptions,
|
||||
};
|
||||
} )
|
||||
)( TaskList );
|
||||
export default TaskList;
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
$foreground-color: var(--wp-admin-theme-color);
|
||||
|
||||
.woocommerce-task-list__item {
|
||||
.woocommerce-task-list__item-title {
|
||||
color: $foreground-color;
|
||||
}
|
||||
|
||||
.woocommerce-task-list__item-before {
|
||||
margin-right: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.woocommerce-task-list__item-after {
|
||||
margin-left: $gap;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.woocommerce-task-list__item-before .woocommerce-task__icon {
|
||||
border-radius: 50%;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.woocommerce-task-list__item-before .woocommerce-task__icon svg {
|
||||
fill: $white;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
.woocommerce-task-list__item-text {
|
||||
.woocommerce-pill {
|
||||
padding: 1px $gap-smaller;
|
||||
margin-left: $gap-smaller;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-complete {
|
||||
.woocommerce-task__icon {
|
||||
background-color: var(--wp-admin-theme-color);
|
||||
}
|
||||
|
||||
.woocommerce-task-list__item-title {
|
||||
color: $gray-700;
|
||||
}
|
||||
|
||||
.woocommerce-task-list__item-content {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Icon, check } from '@wordpress/icons';
|
||||
import { Button } from '@wordpress/components';
|
||||
import { Text } from '@woocommerce/experimental';
|
||||
import { __experimentalListItem as ListItem } from '@woocommerce/components';
|
||||
import classnames from 'classnames';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './task-item.scss';
|
||||
import sanitizeHTML from '../lib/sanitize-html';
|
||||
|
||||
type TaskItemProps = {
|
||||
title: string;
|
||||
completed: boolean;
|
||||
onClick: () => void;
|
||||
isDismissable?: boolean;
|
||||
onDismiss?: () => void;
|
||||
additionalInfo?: string;
|
||||
time?: string;
|
||||
content?: string;
|
||||
expanded?: boolean;
|
||||
};
|
||||
|
||||
export const TaskItem: React.FC< TaskItemProps > = ( {
|
||||
completed,
|
||||
title,
|
||||
isDismissable,
|
||||
onDismiss,
|
||||
onClick,
|
||||
additionalInfo,
|
||||
time,
|
||||
content,
|
||||
expanded = false,
|
||||
} ) => {
|
||||
const className = classnames( 'woocommerce-task-list__item', {
|
||||
'is-complete': completed,
|
||||
} );
|
||||
return (
|
||||
<ListItem
|
||||
disableGutters={ false }
|
||||
className={ className }
|
||||
onClick={ onClick }
|
||||
animation="slide-right"
|
||||
>
|
||||
<div className="woocommerce-task-list__item-before">
|
||||
<div className="woocommerce-task__icon">
|
||||
{ completed && <Icon icon={ check } /> }
|
||||
</div>
|
||||
</div>
|
||||
<div className="woocommerce-task-list__item-text">
|
||||
<span className="woocommerce-task-list__item-title">
|
||||
<Text
|
||||
as="div"
|
||||
variant={ completed ? 'body.small' : 'button' }
|
||||
>
|
||||
{ title }
|
||||
{ additionalInfo && (
|
||||
<div
|
||||
className="woocommerce-task__additional-info"
|
||||
dangerouslySetInnerHTML={ sanitizeHTML(
|
||||
additionalInfo
|
||||
) }
|
||||
></div>
|
||||
) }
|
||||
{ expanded && content && (
|
||||
<div className="woocommerce-task-list__item-content">
|
||||
{ content }
|
||||
</div>
|
||||
) }
|
||||
{ time && ! completed && (
|
||||
<div className="woocommerce-task__estimated-time">
|
||||
{ time }
|
||||
</div>
|
||||
) }
|
||||
</Text>
|
||||
</span>
|
||||
</div>
|
||||
{ onDismiss && isDismissable && ! completed && (
|
||||
<div className="woocommerce-task-list__item-after">
|
||||
<Button
|
||||
data-testid={ `dismiss-button` }
|
||||
isTertiary
|
||||
onClick={ (
|
||||
event: React.MouseEvent | React.KeyboardEvent
|
||||
) => {
|
||||
event.stopPropagation();
|
||||
onDismiss();
|
||||
} }
|
||||
>
|
||||
{ __( 'Dismiss', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
</div>
|
||||
) }
|
||||
</ListItem>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { cloneElement, useRef, useEffect } from '@wordpress/element';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
import { PLUGINS_STORE_NAME, WCDataSelector } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { recordTaskViewEvent } from './tasks';
|
||||
|
||||
type TaskStepProps = {
|
||||
taskContainer?: React.ReactElement;
|
||||
query: { task?: string };
|
||||
};
|
||||
|
||||
export const TaskStep: React.FC< TaskStepProps > = ( {
|
||||
taskContainer,
|
||||
query,
|
||||
} ) => {
|
||||
const prevTaskRef = useRef< string >();
|
||||
const { isJetpackConnected, activePlugins, installedPlugins } = useSelect(
|
||||
( select: WCDataSelector ) => {
|
||||
const {
|
||||
getActivePlugins,
|
||||
getInstalledPlugins,
|
||||
isJetpackConnected: getIsJetpackConnected,
|
||||
} = select( PLUGINS_STORE_NAME );
|
||||
|
||||
return {
|
||||
activePlugins: getActivePlugins(),
|
||||
isJetpackConnected: getIsJetpackConnected(),
|
||||
installedPlugins: getInstalledPlugins(),
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
const recordTaskView = () => {
|
||||
const { task: taskName } = query;
|
||||
|
||||
if ( ! taskName ) {
|
||||
return;
|
||||
}
|
||||
|
||||
recordTaskViewEvent(
|
||||
taskName,
|
||||
isJetpackConnected,
|
||||
activePlugins,
|
||||
installedPlugins
|
||||
);
|
||||
};
|
||||
|
||||
useEffect( () => {
|
||||
const { task } = query;
|
||||
if ( prevTaskRef.current !== task ) {
|
||||
window.document.documentElement.scrollTop = 0;
|
||||
}
|
||||
prevTaskRef.current = task;
|
||||
recordTaskView();
|
||||
}, [ query ] );
|
||||
|
||||
if ( ! taskContainer || ! query.task ) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div className="woocommerce-task-dashboard__container">
|
||||
{ cloneElement( taskContainer, {
|
||||
query,
|
||||
} ) }
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -12,23 +12,45 @@ import userEvent from '@testing-library/user-event';
|
|||
import apiFetch from '@wordpress/api-fetch';
|
||||
import { SlotFillProvider } from '@wordpress/components';
|
||||
import { recordEvent } from '@woocommerce/tracks';
|
||||
import { useDispatch, useSelect } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { TaskDashboard } from '../index.js';
|
||||
import TaskDashboard from '../';
|
||||
import { TaskList } from '../list';
|
||||
import { getAllTasks } from '../tasks';
|
||||
import { DisplayOption } from '../../header/activity-panel/display-options';
|
||||
|
||||
jest.mock( '@wordpress/api-fetch' );
|
||||
jest.mock( '../tasks' );
|
||||
jest.mock( '../tasks', () => ( {
|
||||
recordTaskViewEvent: jest.fn(),
|
||||
getAllTasks: jest.fn(),
|
||||
} ) );
|
||||
jest.mock( '../../dashboard/components/cart-modal', () => null );
|
||||
jest.mock( '@woocommerce/tracks', () => ( { recordEvent: jest.fn() } ) );
|
||||
jest.mock( '@woocommerce/data', () => ( {} ) );
|
||||
jest.mock( '@wordpress/data', () => ( {
|
||||
...jest.requireActual( '@wordpress/data' ),
|
||||
useSelect: jest.fn().mockReturnValue( {
|
||||
profileItems: {},
|
||||
} ),
|
||||
useDispatch: jest.fn(),
|
||||
} ) );
|
||||
|
||||
const TASK_LIST_HEADING = 'Get ready to start selling';
|
||||
const EXTENDED_TASK_LIST_HEADING = 'Things to do next';
|
||||
|
||||
describe( 'TaskDashboard and TaskList', () => {
|
||||
const updateOptions = jest.fn();
|
||||
const createNotice = jest.fn();
|
||||
beforeEach( () => {
|
||||
useDispatch.mockImplementation( () => ( {
|
||||
updateOptions,
|
||||
createNotice,
|
||||
installAndActivatePlugins: jest.fn(),
|
||||
} ) );
|
||||
} );
|
||||
afterEach( () => jest.clearAllMocks() );
|
||||
const MockTask = () => {
|
||||
return <div>mock task</div>;
|
||||
|
@ -124,14 +146,7 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
it( 'renders the "Get ready to start selling" and "Things to do next" tasks lists', async () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
getAllTasks.mockReturnValue( tasks );
|
||||
const { container } = render(
|
||||
<TaskDashboard
|
||||
dismissedTasks={ [] }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
updateOptions={ () => {} }
|
||||
/>
|
||||
);
|
||||
const { container } = render( <TaskDashboard query={ {} } /> );
|
||||
|
||||
// Wait for the setup task list to render.
|
||||
expect(
|
||||
|
@ -147,14 +162,7 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
it( 'renders a dismiss button for tasks that are optional and incomplete', async () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
getAllTasks.mockReturnValue( tasks );
|
||||
const { container } = render(
|
||||
<TaskDashboard
|
||||
dismissedTasks={ [] }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
updateOptions={ () => {} }
|
||||
/>
|
||||
);
|
||||
const { container } = render( <TaskDashboard query={ {} } /> );
|
||||
|
||||
// The `optional` task has a dismiss button.
|
||||
expect(
|
||||
|
@ -176,13 +184,7 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
apiFetch.mockResolvedValue( {} );
|
||||
getAllTasks.mockReturnValue( tasks );
|
||||
const { container } = render(
|
||||
<TaskDashboard
|
||||
dismissedTasks={ [] }
|
||||
isSetupTaskListHidden={ true }
|
||||
profileItems={ {} }
|
||||
query={ { task: 'optional' } }
|
||||
updateOptions={ () => {} }
|
||||
/>
|
||||
<TaskDashboard query={ { task: 'optional' } } />
|
||||
);
|
||||
|
||||
// Wait for the task to render.
|
||||
|
@ -190,17 +192,14 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
} );
|
||||
|
||||
it( 'renders only the extended task list', () => {
|
||||
useSelect.mockImplementation( () => ( {
|
||||
dismissedTasks: [],
|
||||
isSetupTaskListHidden: true,
|
||||
profileItems: {},
|
||||
} ) );
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
getAllTasks.mockReturnValue( tasks );
|
||||
const { queryByText } = render(
|
||||
<TaskDashboard
|
||||
dismissedTasks={ [] }
|
||||
isSetupTaskListHidden={ true }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
updateOptions={ () => {} }
|
||||
/>
|
||||
);
|
||||
const { queryByText } = render( <TaskDashboard query={ {} } /> );
|
||||
|
||||
expect( queryByText( TASK_LIST_HEADING ) ).toBeNull();
|
||||
|
||||
|
@ -208,14 +207,11 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
} );
|
||||
|
||||
it( 'sets homescreen layout default when dismissed', () => {
|
||||
const updateOptions = jest.fn();
|
||||
const { getByRole } = render(
|
||||
<TaskList
|
||||
dismissedTasks={ [] }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
dismissedTasks={ [] }
|
||||
trackedCompletedTasks={ shorterTasksList }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ shorterTasksList }
|
||||
/>
|
||||
);
|
||||
|
@ -232,15 +228,12 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'sets homescreen layout default when completed', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
act( () => {
|
||||
render(
|
||||
<TaskList
|
||||
dismissedTasks={ [] }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
dismissedTasks={ [] }
|
||||
trackedCompletedTasks={ shorterTasksList }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ shorterTasksList }
|
||||
/>
|
||||
);
|
||||
|
@ -254,16 +247,13 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'hides the setup task list if there are no visible tasks', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
const { setup } = tasks;
|
||||
const { queryByText } = render(
|
||||
<TaskList
|
||||
dismissedTasks={ [ 'optional', 'required', 'completed' ] }
|
||||
isComplete={ false }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ [] }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ [ ...setup, notVisibleTask ] }
|
||||
/>
|
||||
);
|
||||
|
@ -273,16 +263,13 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'hides the extended task list if there are no visible tasks', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
const { extension } = tasks;
|
||||
const { queryByText } = render(
|
||||
<TaskList
|
||||
dismissedTasks={ [ 'extension' ] }
|
||||
isComplete={ false }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ [] }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ [ ...extension, notVisibleTask ] }
|
||||
/>
|
||||
);
|
||||
|
@ -292,16 +279,13 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'sets setup tasks list as completed', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
act( () => {
|
||||
render(
|
||||
<TaskList
|
||||
dismissedTasks={ [] }
|
||||
isComplete={ false }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ shorterTasksList }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ shorterTasksList }
|
||||
/>
|
||||
);
|
||||
|
@ -315,16 +299,13 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'sets extended tasks list as completed', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
act( () => {
|
||||
render(
|
||||
<TaskList
|
||||
dismissedTasks={ [] }
|
||||
isComplete={ false }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ [] }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ shorterTasksList }
|
||||
name={ 'extended_task_list' }
|
||||
/>
|
||||
|
@ -338,17 +319,14 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'sets setup tasks list (with only dismissed tasks) as completed', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
const { setup } = tasks;
|
||||
act( () => {
|
||||
render(
|
||||
<TaskList
|
||||
dismissedTasks={ [ 'optional', 'required', 'completed' ] }
|
||||
isComplete={ false }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ [] }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ setup }
|
||||
/>
|
||||
);
|
||||
|
@ -362,17 +340,14 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'sets extended tasks list (with only dismissed tasks) as completed', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
const { extension } = tasks;
|
||||
act( () => {
|
||||
render(
|
||||
<TaskList
|
||||
dismissedTasks={ [ 'extension' ] }
|
||||
isComplete={ false }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ [] }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ extension }
|
||||
name={ 'extended_task_list' }
|
||||
/>
|
||||
|
@ -386,17 +361,14 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'sets setup tasks list as incomplete', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
const { setup } = tasks;
|
||||
act( () => {
|
||||
render(
|
||||
<TaskList
|
||||
dismissedTasks={ [] }
|
||||
isComplete={ true }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ shorterTasksList }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ [ ...setup ] }
|
||||
/>
|
||||
);
|
||||
|
@ -410,17 +382,14 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'sets extended tasks list as incomplete', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
const { extension } = tasks;
|
||||
act( () => {
|
||||
render(
|
||||
<TaskList
|
||||
dismissedTasks={ [] }
|
||||
isComplete={ true }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ shorterTasksList }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ extension }
|
||||
name={ 'extended_task_list' }
|
||||
/>
|
||||
|
@ -434,16 +403,13 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'adds an untracked completed task', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
const { setup, extension } = tasks;
|
||||
act( () => {
|
||||
render(
|
||||
<TaskList
|
||||
dismissedTasks={ [] }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ [] }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ [ ...setup, ...extension ] }
|
||||
/>
|
||||
);
|
||||
|
@ -456,16 +422,13 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'removes an incomplete but already tracked task from tracked tasks list', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
const { setup, extension } = tasks;
|
||||
act( () => {
|
||||
render(
|
||||
<TaskList
|
||||
dismissedTasks={ [] }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ [ 'completed', 'extension' ] }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ [ ...setup, ...extension ] }
|
||||
/>
|
||||
);
|
||||
|
@ -478,16 +441,13 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'adds an untracked completed task and removes an incomplete but already tracked task from tracked tasks list', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
const { setup, extension } = tasks;
|
||||
act( () => {
|
||||
render(
|
||||
<TaskList
|
||||
dismissedTasks={ [] }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ [ 'extension' ] }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ [ ...setup, ...extension ] }
|
||||
/>
|
||||
);
|
||||
|
@ -500,15 +460,12 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'does not add untracked completed (but dismissed) tasks', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
act( () => {
|
||||
render(
|
||||
<TaskList
|
||||
dismissedTasks={ [ 'completed-1' ] }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ [] }
|
||||
updateOptions={ updateOptions }
|
||||
tasks={ shorterTasksList }
|
||||
/>
|
||||
);
|
||||
|
@ -521,18 +478,13 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'dismisses a task', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
const createNotice = jest.fn();
|
||||
const { extension } = tasks;
|
||||
const { getByText } = render(
|
||||
<TaskList
|
||||
dismissedTasks={ [] }
|
||||
isComplete={ false }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ [] }
|
||||
updateOptions={ updateOptions }
|
||||
createNotice={ createNotice }
|
||||
tasks={ extension }
|
||||
name={ 'extended_task_list' }
|
||||
/>
|
||||
|
@ -547,8 +499,6 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
|
||||
it( 'calls the "onDismiss" callback after dismissing a task', () => {
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
const updateOptions = jest.fn();
|
||||
const createNotice = jest.fn();
|
||||
const callback = jest.fn();
|
||||
const { extension } = tasks;
|
||||
extension[ 0 ].onDismiss = callback;
|
||||
|
@ -556,11 +506,8 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
<TaskList
|
||||
dismissedTasks={ [] }
|
||||
isComplete={ false }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
trackedCompletedTasks={ [] }
|
||||
updateOptions={ updateOptions }
|
||||
createNotice={ createNotice }
|
||||
tasks={ extension }
|
||||
name={ 'extended_task_list' }
|
||||
/>
|
||||
|
@ -571,23 +518,22 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
} );
|
||||
|
||||
it( 'sorts the extended task list tasks by completion status', () => {
|
||||
useSelect.mockImplementation( () => ( {
|
||||
dismissedTasks: [],
|
||||
isSetupTaskListHidden: true,
|
||||
profileItems: {},
|
||||
} ) );
|
||||
apiFetch.mockResolvedValue( {} );
|
||||
getAllTasks.mockReturnValue( {
|
||||
extension: [ completedExtensionTask, ...tasks.extension ],
|
||||
} );
|
||||
const { queryAllByRole, queryByText } = render(
|
||||
<TaskDashboard
|
||||
dismissedTasks={ [] }
|
||||
isSetupTaskListHidden={ true }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
updateOptions={ () => {} }
|
||||
/>
|
||||
const { queryByText, container } = render(
|
||||
<TaskDashboard query={ {} } />
|
||||
);
|
||||
|
||||
const visibleTasks = container.querySelectorAll( 'li' );
|
||||
expect( queryByText( EXTENDED_TASK_LIST_HEADING ) ).not.toBeNull();
|
||||
|
||||
const visibleTasks = queryAllByRole( 'menuitem' );
|
||||
expect( visibleTasks ).toHaveLength( 2 );
|
||||
expect( visibleTasks[ 0 ] ).toHaveTextContent(
|
||||
'This task is an extension'
|
||||
|
@ -598,18 +544,10 @@ describe( 'TaskDashboard and TaskList', () => {
|
|||
} );
|
||||
|
||||
it( 'correctly toggles the extension task list', () => {
|
||||
const updateOptions = jest.fn();
|
||||
|
||||
const { getByText } = render(
|
||||
<SlotFillProvider>
|
||||
<DisplayOption.Slot />
|
||||
<TaskDashboard
|
||||
dismissedTasks={ [] }
|
||||
isSetupTaskListHidden={ true }
|
||||
profileItems={ {} }
|
||||
query={ {} }
|
||||
updateOptions={ updateOptions }
|
||||
/>
|
||||
<TaskDashboard query={ {} } />
|
||||
</SlotFillProvider>
|
||||
);
|
||||
|
||||
|
|
|
@ -8538,6 +8538,16 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-20.2.0.tgz",
|
||||
"integrity": "sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA=="
|
||||
},
|
||||
"@types/yauzl": {
|
||||
"version": "2.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
|
||||
"integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "4.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.22.0.tgz",
|
||||
|
@ -9246,7 +9256,7 @@
|
|||
"@wordpress/element": "2.19.0",
|
||||
"@wordpress/i18n": "3.17.0",
|
||||
"@wordpress/notices": "^2.11.0",
|
||||
"classnames": "2.2.6",
|
||||
"classnames": "2.3.1",
|
||||
"prop-types": "15.7.2",
|
||||
"react-transition-group": "4.4.1"
|
||||
},
|
||||
|
@ -9264,9 +9274,9 @@
|
|||
}
|
||||
},
|
||||
"classnames": {
|
||||
"version": "2.2.6",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
|
||||
"integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==",
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz",
|
||||
"integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
|
@ -11992,12 +12002,6 @@
|
|||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"chownr": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
||||
"dev": true
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
|
@ -12221,18 +12225,6 @@
|
|||
"debug": "^4.1.1",
|
||||
"get-stream": "^5.1.0",
|
||||
"yauzl": "^2.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/yauzl": {
|
||||
"version": "2.9.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.1.tgz",
|
||||
"integrity": "sha512-A1b8SU4D10uoPjwb0lnHmmu8wZhR9d+9o2PKBQT2jU5YPTKsxac6M2qGAdY7VcL+dHHhARVUDmeg0rOrcd9EjA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"fast-glob": {
|
||||
|
@ -12878,30 +12870,6 @@
|
|||
"tar-fs": "^2.0.0",
|
||||
"unbzip2-stream": "^1.3.3",
|
||||
"ws": "^7.2.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"tar-fs": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
|
||||
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chownr": "^1.1.1",
|
||||
"mkdirp-classic": "^0.5.2",
|
||||
"pump": "^3.0.0",
|
||||
"tar-stream": "^2.1.4"
|
||||
}
|
||||
},
|
||||
"unbzip2-stream": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
|
||||
"integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer": "^5.2.1",
|
||||
"through": "^2.3.8"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"read-pkg": {
|
||||
|
@ -37475,6 +37443,26 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"tar-fs": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
|
||||
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chownr": "^1.1.1",
|
||||
"mkdirp-classic": "^0.5.2",
|
||||
"pump": "^3.0.0",
|
||||
"tar-stream": "^2.1.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"chownr": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"tar-stream": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
|
||||
|
@ -38288,6 +38276,16 @@
|
|||
"which-boxed-primitive": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"unbzip2-stream": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz",
|
||||
"integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"buffer": "^5.2.1",
|
||||
"through": "^2.3.8"
|
||||
}
|
||||
},
|
||||
"unc-path-regex": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
|
||||
|
|
|
@ -27,8 +27,8 @@ export { default as ImageUpload } from './image-upload';
|
|||
export { default as Link } from './link';
|
||||
export {
|
||||
default as List,
|
||||
ExperimentalList,
|
||||
ExperimentalListItem,
|
||||
ExperimentalList as __experimentalList,
|
||||
ExperimentalListItem as __experimentalListItem,
|
||||
} from './list';
|
||||
export { default as MenuItem } from './ellipsis-menu/menu-item';
|
||||
export { default as MenuTitle } from './ellipsis-menu/menu-title';
|
||||
|
|
|
@ -49,6 +49,7 @@ export const ExperimentalList: React.FC< ListProps > = ( {
|
|||
in={ inTransition }
|
||||
enter={ enter }
|
||||
exit={ exit }
|
||||
classNames="woocommerce-list__item"
|
||||
>
|
||||
{ cloneElement( child, {
|
||||
animation: animationProp,
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
"@wordpress/element": "2.19.0",
|
||||
"@wordpress/i18n": "3.17.0",
|
||||
"@wordpress/notices": "^2.11.0",
|
||||
"classnames": "2.2.6",
|
||||
"classnames": "2.3.1",
|
||||
"prop-types": "15.7.2",
|
||||
"react-transition-group": "4.4.1"
|
||||
},
|
||||
|
|
|
@ -68,4 +68,5 @@ export type PluginSelectors = {
|
|||
getActivePlugins: WPDataSelector< typeof getActivePlugins >;
|
||||
getInstalledPlugins: WPDataSelector< typeof getInstalledPlugins >;
|
||||
getRecommendedPlugins: WPDataSelector< typeof getRecommendedPlugins >;
|
||||
isJetpackConnected: WPDataSelector< typeof isJetpackConnected >;
|
||||
} & WPDataSelectors;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
# Unreleased
|
||||
|
||||
- Export component ExperimentalList and ExperimentalListItem as List and ListItem.
|
||||
|
||||
# 1.0.0
|
||||
|
||||
- Initial package
|
||||
|
|
|
@ -119,6 +119,7 @@ Release and roadmap notes are available on the [WooCommerce Developers Blog](htt
|
|||
- Update: Update choose niche note cta URL #6733
|
||||
- Update: UI updates to Payment Task screen #6766
|
||||
- Update: Adding setup required icon for non-configured payment methods #6811
|
||||
- Update: Task list component with new Experimental Task list. #6849
|
||||
|
||||
== 2.2.0 3/30/2021 ==
|
||||
|
||||
|
|
|
@ -25,11 +25,11 @@ export class WcHomescreen extends BasePage {
|
|||
|
||||
async getTaskList() {
|
||||
await page.waitForSelector(
|
||||
'.woocommerce-task-card .woocommerce-list__item-title'
|
||||
'.woocommerce-task-card .woocommerce-task-list__item-title'
|
||||
);
|
||||
await waitForElementByText( 'p', 'Get ready to start selling' );
|
||||
const list = await this.page.$$eval(
|
||||
'.woocommerce-task-card .woocommerce-list__item-title',
|
||||
'.woocommerce-task-card .woocommerce-task-list__item-title',
|
||||
( items ) => items.map( ( item ) => item.textContent )
|
||||
);
|
||||
return list.map( ( item: string | null ) => {
|
||||
|
|
Loading…
Reference in New Issue