Cleanup and deprecate task properties and methods (#35450)

* Remove unused sectioned task code

* Remove section task type and update getVisibleTasks logic

* Clean up task list and deprecate methods/properties

* Add changelog

* Fix lint

* Remove snooze tests

* Remove snooze JS tests
This commit is contained in:
Chi-Hsuan Huang 2022-11-03 09:22:36 +08:00 committed by GitHub
parent 3df6dcd6be
commit 76f99a482f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 57 additions and 1222 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: dev
Update task list types and getVisibleTasks logic

View File

@ -53,15 +53,6 @@ export type DeprecatedTaskType = {
type?: string;
};
export type TaskListSection = {
id: string;
title: string;
description: string;
image: string;
tasks: string[];
isComplete: boolean;
};
export type TaskListType = {
id: string;
title: string;
@ -73,7 +64,6 @@ export type TaskListType = {
displayProgressHeader: boolean;
keepCompletedTaskList: 'yes' | 'no';
showCESFeedback?: boolean;
sections?: TaskListSection[];
isToggleable?: boolean;
isCollapsible?: boolean;
isExpandable?: boolean;

View File

@ -7,8 +7,4 @@ import { TaskType } from './types';
* Filters tasks to only visible tasks, taking in account snoozed tasks.
*/
export const getVisibleTasks = ( tasks: TaskType[] ) =>
tasks.filter(
( task ) =>
! task.isDismissed &&
( ! task.isSnoozed || task.snoozedUntil < Date.now() )
);
tasks.filter( ( task ) => ! task.isDismissed );

View File

@ -20,15 +20,13 @@ import { recordEvent } from '@woocommerce/tracks';
*/
import { DisplayOption } from '~/activity-panel/display-options';
import { Task } from './task';
import { TasksPlaceholder, TasksPlaceholderProps } from './placeholder';
import { TasksPlaceholder } from './placeholder';
import './tasks.scss';
import { TaskList } from './task-list';
import { TaskList as TwoColumnTaskList } from '../two-column-tasks/task-list';
import { SectionedTaskList } from '../two-column-tasks/sectioned-task-list';
import TwoColumnTaskListPlaceholder from '../two-column-tasks/placeholder';
import '../two-column-tasks/style.scss';
import { getAdminSetting } from '~/utils/admin-settings';
import { SectionedTaskListPlaceholder } from '~/two-column-tasks/sectioned-task-list-placeholder';
export type TasksProps = {
query: { task?: string };

View File

@ -235,56 +235,4 @@ describe( 'TaskList', () => {
queryByText( dismissedTask[ 0 ].title )
).not.toBeInTheDocument();
} );
it( 'should not display isSnoozed tasks', () => {
const dismissedTask = [
{
...tasks.setup[ 0 ],
isSnoozed: true,
snoozedUntil: Date.now() + 10000,
},
];
const { queryByText } = render(
<TaskList
id="setup"
eventPrefix="tasklist_"
tasks={ dismissedTask }
title="List title"
query={ {} }
isVisible={ true }
isHidden={ false }
isComplete={ false }
displayProgressHeader={ false }
keepCompletedTaskList="no"
/>
);
expect(
queryByText( dismissedTask[ 0 ].title )
).not.toBeInTheDocument();
} );
it( 'should display a snoozed task if snoozedUntil passed the current timestamp', () => {
const dismissedTask = [
{
...tasks.setup[ 0 ],
isSnoozed: true,
snoozedUntil: Date.now() - 1000,
},
];
const { queryByText } = render(
<TaskList
id="setup"
eventPrefix="tasklist_"
tasks={ dismissedTask }
title="List title"
query={ {} }
isVisible={ true }
isHidden={ false }
isComplete={ false }
displayProgressHeader={ false }
keepCompletedTaskList="no"
/>
);
expect( queryByText( dismissedTask[ 0 ].title ) ).toBeInTheDocument();
} );
} );

View File

@ -1,36 +0,0 @@
.woocommerce-task-section-header__container {
display: flex;
.woocommerce-task-header__illustration {
max-width: 150px;
width: 34%;
margin-left: auto;
margin-right: 7%;
display: flex;
align-items: center;
.illustration-background {
max-width: 100%;
}
}
@at-root .woocommerce-setup-panel & .woocommerce-task-header__contents p {
font-size: 13px;
}
.woocommerce-task-header__contents p {
font-size: 16px;
}
@at-root .woocommerce-setup-panel & .woocommerce-task-header__contents h1 {
font-size: 14px;
font-weight: 600;
}
.woocommerce-task-header__contents h1 {
font-size: 20px;
line-height: 28px;
padding: 0;
}
}

View File

@ -1,30 +0,0 @@
/**
* Internal dependencies
*/
import './section-header.scss';
type Props = {
title: string;
description: string;
image: string;
};
const SectionHeader: React.FC< Props > = ( { title, description, image } ) => {
return (
<div className="woocommerce-task-header__contents-container woocommerce-task-section-header__container">
<div className="woocommerce-task-header__contents">
<h1>{ title }</h1>
<p>{ description }</p>
</div>
<div className="woocommerce-task-header__illustration">
<img
src={ image }
alt={ title }
className="illustration-background"
/>
</div>
</div>
);
};
export default SectionHeader;

View File

@ -1,58 +0,0 @@
/**
* External dependencies
*/
import { Badge } from '@woocommerce/components';
import { TaskListSection, TaskType } from '@woocommerce/data';
import { Icon, check } from '@wordpress/icons';
import { Text } from '@woocommerce/experimental';
/**
* Internal dependencies
*/
import SectionHeader from './headers/section-header';
type SectionPanelTitleProps = {
section: TaskListSection;
active: boolean;
tasks: TaskType[];
};
export const SectionPanelTitle: React.FC< SectionPanelTitleProps > = ( {
section,
active,
tasks,
} ) => {
if ( active ) {
return (
<div className="wooocommerce-task-card__header-container">
<div className="wooocommerce-task-card__header">
<SectionHeader { ...section } />
</div>
</div>
);
}
const uncompletedTasksCount = tasks.filter(
( task ) => ! task.isComplete && section.tasks.includes( task.id )
).length;
const isComplete = section.isComplete || uncompletedTasksCount === 0;
return (
<>
<Text
className="woocommerce-task-header-collapsed"
variant="title.small"
size="20"
lineHeight="28px"
>
{ section.title }
</Text>
{ ! isComplete && <Badge count={ uncompletedTasksCount } /> }
{ isComplete && (
<div className="woocommerce-task__icon">
<Icon icon={ check } />
</div>
) }
</>
);
};

View File

@ -1,75 +0,0 @@
/**
* Internal dependencies
*/
import './style.scss';
type TasksPlaceholderProps = {
numTasks?: number;
query: {
task?: string;
};
};
const SectionedTaskListPlaceholder: React.FC< TasksPlaceholderProps > = (
props
) => {
const { numTasks = 3 } = props;
return (
<div
className={
'woocommerce-task-dashboard__container woocommerce-sectioned-task-list'
}
>
<div className="components-card is-size-large woocommerce-task-card woocommerce-homescreen-card is-loading ">
<div className="components-card__header is-size-medium">
<div className="wooocommerce-task-card__header">
<div className="is-placeholder"> </div>
</div>
</div>
<ul className="woocommerce-experimental-list">
{ Array.from( new Array( numTasks ) ).map( ( v, i ) => (
<li
tabIndex={ i }
key={ i }
className="woocommerce-experimental-list__item woocommerce-task-list__item"
>
<div className="woocommerce-task-list__item-before">
<div className="is-placeholder"></div>
</div>
<div className="woocommerce-task-list__item-text">
<div className="components-truncate components-text is-placeholder"></div>
</div>
</li>
) ) }
</ul>
</div>
<div className="is-loading components-panel__body woocommerce-task-card">
<div className="components-panel__body-title">
<div className="components-button components-panel__body-toggle">
<div className="woocommerce-task-list__item-text">
<div className="components-truncate components-text is-placeholder"></div>
</div>
<div className="woocommerce-task-list__item-after">
<div className="is-placeholder"></div>
</div>
</div>
</div>
</div>
<div className="is-loading components-panel__body woocommerce-task-card">
<div className="components-panel__body-title">
<div className="components-button components-panel__body-toggle">
<div className="woocommerce-task-list__item-text">
<div className="components-truncate components-text is-placeholder"></div>
</div>
<div className="woocommerce-task-list__item-after">
<div className="is-placeholder"></div>
</div>
</div>
</div>
</div>
</div>
);
};
export { SectionedTaskListPlaceholder };

View File

@ -1,165 +0,0 @@
.woocommerce-sectioned-task-list {
.components-panel {
width: 100%;
background: transparent;
border: 0;
}
.components-panel__body {
padding-bottom: 0;
margin-bottom: $gap-smaller;
background: #fff;
border: 1px solid $gray-200;
&.is-opened {
padding-bottom: 0;
}
.components-panel__body-title {
margin-bottom: 0;
border-bottom: 1px solid #e0e0e0;
&:hover {
border-bottom: 1px solid #e0e0e0;
}
@at-root .woocommerce-setup-panel & > .components-button {
font-size: 14px;
}
> .components-button {
font-size: 20px;
font-weight: 400;
padding-top: 20px;
padding-bottom: 20px;
}
.components-panel__arrow {
right: $gap-large;
}
.woocommerce-task-header__contents p:first-of-type {
margin-top: $gap-small;
}
}
.wooocommerce-task-card__header-container {
width: 100%;
border-bottom: none;
}
.components-panel__body-toggle {
box-shadow: none;
padding-left: $gap-large;
}
&.is-opened .components-panel__body-toggle {
width: 100%;
padding: 0;
.components-panel__arrow {
top: 32px;
}
}
.woocommerce-experimental-list {
width: calc(100% + 32px);
margin: 0 -16px;
}
}
ul li.woocommerce-task-list__item {
padding-top: $gap;
padding-bottom: $gap;
min-height: 72px;
&.is-disabled {
pointer-events: none;
}
&:not(.complete)
.woocommerce-task-list__item-before
.woocommerce-task__icon {
border-color: $gray-300;
}
.woocommerce-task-list__item-expandable-content {
line-height: $gap;
}
}
.woocommerce-task-list__item.complete .woocommerce-task__icon {
background-color: $alert-green;
}
.components-panel__body-title {
.woocommerce-badge {
width: 28px;
height: 28px;
margin-left: $gap-small;
}
.woocommerce-task__icon {
margin-left: $gap;
background-color: $alert-green;
border-radius: 50%;
width: 24px;
height: 24px;
svg {
fill: #fff;
position: relative;
}
}
}
> .is-loading {
border: none;
margin-bottom: 8px;
.woocommerce-task-list__item .woocommerce-task-list__item-before {
padding: 0 0 0 $gap-large;
}
&.components-panel__body .components-panel__body-title .woocommerce-task-list__item-text {
width: 50%;
.is-placeholder {
width: 100%;
}
}
&.components-panel__body .woocommerce-task-list__item-after {
margin-left: $gap;
.is-placeholder {
height: 24px;
width: 24px;
border-radius: 50%;
}
}
}
}
.woocommerce-setup-panel {
.two-column-experiment {
h1 {
font-size: 16px;
font-weight: 600;
}
}
.woocommerce-task-header-collapsed {
font-size: 14px;
line-height: 20px;
font-weight: bold;
}
.woocommerce-task-progress-header {
padding: $gap;
margin-bottom: $gap-smaller;
background: #fff;
border: 1px solid $gray-200;
.woocommerce-task-progress-header__title {
padding-top: 4px;
}
.woocommerce-ellipsis-menu {
display: none;
}
}
}

View File

@ -1,209 +0,0 @@
/**
* External dependencies
*/
import { useEffect, useRef, useState, useContext } from '@wordpress/element';
import { Panel, PanelBody, PanelRow } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { ONBOARDING_STORE_NAME, getVisibleTasks } from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';
import { List } from '@woocommerce/experimental';
import classnames from 'classnames';
/**
* Internal dependencies
*/
import '../tasks/task-list.scss';
import './sectioned-task-list.scss';
import TaskListCompleted from './completed';
import { TaskListProps } from '~/tasks/task-list';
import { ProgressHeader } from '~/task-lists/progress-header';
import { SectionPanelTitle } from './section-panel-title';
import { TaskListItem } from './task-list-item';
import { TaskListCompletedHeader } from './completed-header';
import { LayoutContext } from '~/layout';
type PanelBodyProps = Omit< PanelBody.Props, 'title' | 'onToggle' > & {
title: string | React.ReactNode | undefined;
onToggle?: ( isOpen: boolean ) => void;
};
const PanelBodyWithUpdatedType =
PanelBody as React.ComponentType< PanelBodyProps >;
export const SectionedTaskList: React.FC< TaskListProps > = ( {
query,
id,
eventPrefix,
tasks,
keepCompletedTaskList,
isComplete,
sections,
displayProgressHeader,
cesHeader = true,
} ) => {
const { profileItems } = useSelect( ( select ) => {
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
return {
profileItems: getProfileItems(),
};
} );
const { hideTaskList, keepCompletedTaskList: keepCompletedTasks } =
useDispatch( ONBOARDING_STORE_NAME );
const [ openPanel, setOpenPanel ] = useState< string | null >(
sections?.find( ( section ) => ! section.isComplete )?.id || null
);
const layoutContext = useContext( LayoutContext );
const prevQueryRef = useRef( query );
const visibleTasks = getVisibleTasks( tasks );
const recordTaskListView = () => {
if ( query.task ) {
return;
}
recordEvent( `${ eventPrefix }view`, {
number_tasks: visibleTasks.length,
store_connected: profileItems.wccom_connected,
context: layoutContext.toString(),
} );
};
useEffect( () => {
recordTaskListView();
}, [] );
useEffect( () => {
const { task: prevTask } = prevQueryRef.current;
const { task } = query;
if ( prevTask !== task ) {
window.document.documentElement.scrollTop = 0;
prevQueryRef.current = query;
}
}, [ query ] );
const hideTasks = () => {
hideTaskList( id );
};
const keepTasks = () => {
keepCompletedTasks( id );
};
let selectedHeaderCard = visibleTasks.find(
( listTask ) => listTask.isComplete === false
);
// If nothing is selected, default to the last task since everything is completed.
if ( ! selectedHeaderCard ) {
selectedHeaderCard = visibleTasks[ visibleTasks.length - 1 ];
}
const getSectionTasks = ( sectionTaskIds: string[] ) => {
return visibleTasks.filter( ( task ) =>
sectionTaskIds.includes( task.id )
);
};
if ( ! visibleTasks.length ) {
return <div className="woocommerce-task-dashboard__container"></div>;
}
if ( isComplete && keepCompletedTaskList !== 'yes' ) {
return (
<>
{ cesHeader ? (
<TaskListCompletedHeader
hideTasks={ hideTasks }
keepTasks={ keepTasks }
customerEffortScore={ true }
/>
) : (
<TaskListCompleted
hideTasks={ hideTasks }
keepTasks={ keepTasks }
twoColumns={ false }
/>
) }
</>
);
}
return (
<>
{ displayProgressHeader ? (
<ProgressHeader taskListId={ id } />
) : null }
<div
className={ classnames(
`woocommerce-task-dashboard__container woocommerce-sectioned-task-list two-column-experiment woocommerce-task-list__${ id }`
) }
>
<Panel>
{ ( sections || [] ).map( ( section ) => (
<PanelBodyWithUpdatedType
key={ section.id }
title={
<SectionPanelTitle
section={ section }
tasks={ tasks }
active={ openPanel === section.id }
/>
}
opened={ openPanel === section.id }
onToggle={ ( isOpen: boolean ) => {
if ( ! isOpen && openPanel === section.id ) {
recordEvent(
`${ eventPrefix }section_closed`,
{
id: section.id,
all: true,
}
);
setOpenPanel( null );
} else {
if ( openPanel ) {
recordEvent(
`${ eventPrefix }section_closed`,
{
id: openPanel,
all: false,
}
);
}
setOpenPanel( section.id );
}
if ( isOpen ) {
recordEvent(
`${ eventPrefix }section_opened`,
{
id: section.id,
}
);
}
} }
initialOpen={ false }
>
<PanelRow>
<List animation="custom">
{ getSectionTasks( section.tasks ).map(
( task ) => (
<TaskListItem
key={ task.id }
task={ task }
eventPrefix={ eventPrefix }
/>
)
) }
</List>
</PanelRow>
</PanelBodyWithUpdatedType>
) ) }
</Panel>
</div>
</>
);
};
export default SectionedTaskList;

View File

@ -1,189 +0,0 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import { getNewPath, navigateTo } from '@woocommerce/navigation';
import {
ONBOARDING_STORE_NAME,
TaskType,
useUserPreferences,
} from '@woocommerce/data';
import { recordEvent } from '@woocommerce/tracks';
import { TaskItem, useSlot } from '@woocommerce/experimental';
import { useCallback, useContext } from '@wordpress/element';
import { useDispatch } from '@wordpress/data';
import { WooOnboardingTaskListItem } from '@woocommerce/onboarding';
import classnames from 'classnames';
/**
* Internal dependencies
*/
import { LayoutContext } from '~/layout';
export type TaskListItemProps = {
task: TaskType;
eventPrefix?: string;
};
export const TaskListItem: React.FC< TaskListItemProps > = ( {
task,
eventPrefix,
} ) => {
const { createNotice } = useDispatch( 'core/notices' );
const {
visitedTask,
dismissTask,
undoDismissTask,
snoozeTask,
undoSnoozeTask,
} = useDispatch( ONBOARDING_STORE_NAME );
const layoutContext = useContext( LayoutContext );
const slot = useSlot(
`woocommerce_onboarding_task_list_item_${ task.id }`
);
const hasFills = Boolean( slot?.fills?.length );
const userPreferences = useUserPreferences();
const getTaskStartedCount = () => {
const trackedStartedTasks =
userPreferences.task_list_tracked_started_tasks;
if ( ! trackedStartedTasks || ! trackedStartedTasks[ task.id ] ) {
return 0;
}
return trackedStartedTasks[ task.id ];
};
const updateTrackStartedCount = () => {
const newCount = getTaskStartedCount() + 1;
const trackedStartedTasks =
userPreferences.task_list_tracked_started_tasks || {};
visitedTask( task.id );
userPreferences.updateUserPreferences( {
task_list_tracked_started_tasks: {
...( trackedStartedTasks || {} ),
[ task.id ]: newCount,
},
} );
};
const trackClick = () => {
recordEvent( `${ eventPrefix }click`, {
task_name: task.id,
context: layoutContext.toString(),
} );
if ( ! task.isComplete ) {
updateTrackStartedCount();
}
};
const onTaskSelected = () => {
trackClick();
if ( task.actionUrl ) {
navigateTo( {
url: task.actionUrl,
} );
return;
}
navigateTo( { url: getNewPath( { task: task.id }, '/', {} ) } );
};
const onDismiss = useCallback( () => {
dismissTask( task.id );
createNotice( 'success', __( 'Task dismissed', 'woocommerce' ), {
actions: [
{
label: __( 'Undo', 'woocommerce' ),
onClick: () => undoDismissTask( task.id ),
},
],
} );
}, [ task.id ] );
const onSnooze = useCallback( () => {
snoozeTask( task.id );
createNotice(
'success',
__( 'Task postponed until tomorrow', 'woocommerce' ),
{
actions: [
{
label: __( 'Undo', 'woocommerce' ),
onClick: () => undoSnoozeTask( task.id ),
},
],
}
);
}, [ task.id ] );
const className = classnames( 'woocommerce-task-list__item', {
complete: task.isComplete,
'is-disabled': task.isDisabled,
} );
const taskItemProps = {
completed: task.isComplete,
onSnooze: task.isSnoozeable && onSnooze,
onDismiss: task.isDismissable && onDismiss,
};
const DefaultTaskItem = useCallback(
( props ) => {
const onClickActions = () => {
if ( props.onClick ) {
trackClick();
return props.onClick();
}
return onTaskSelected();
};
return (
<TaskItem
key={ task.id }
className={ className }
title={ task.title }
completed={ task.isComplete }
expanded={ ! task.isComplete }
additionalInfo={ task.additionalInfo }
onDismiss={ task.isDismissable && onDismiss }
action={ () => {} }
actionLabel={ task.actionLabel }
{ ...props }
onClick={ ( e: React.ChangeEvent ) => {
if ( task.isDisabled || e.target.tagName === 'A' ) {
return;
}
onClickActions();
} }
/>
);
},
[
task.id,
task.title,
task.content,
task.time,
task.actionLabel,
task.isComplete,
]
);
return hasFills ? (
<WooOnboardingTaskListItem.Slot
id={ task.id }
fillProps={ {
defaultTaskItem: DefaultTaskItem,
isComplete: task.isComplete,
...taskItemProps,
} }
/>
) : (
<DefaultTaskItem />
);
};

View File

@ -259,56 +259,4 @@ describe( 'TaskList', () => {
queryByText( dismissedTask[ 0 ].title )
).not.toBeInTheDocument();
} );
it( 'should not display isSnoozed tasks', () => {
const dismissedTask = [
{
...tasks.setup[ 0 ],
isSnoozed: true,
snoozedUntil: Date.now() + 10000,
},
];
const { queryByText } = render(
<TaskList
id="extended"
tasks={ dismissedTask }
title="List title"
query={ {} }
isComplete={ false }
isHidden={ false }
eventPrefix={ '' }
displayProgressHeader={ false }
keepCompletedTaskList="no"
isVisible={ true }
/>
);
expect(
queryByText( dismissedTask[ 0 ].title )
).not.toBeInTheDocument();
} );
it( 'should display a snoozed task if snoozedUntil passed the current timestamp', () => {
const dismissedTask = [
{
...tasks.setup[ 0 ],
isSnoozed: true,
snoozedUntil: Date.now() - 1000,
},
];
const { queryByText } = render(
<TaskList
id="extended"
tasks={ dismissedTask }
title="List title"
query={ {} }
isComplete={ false }
isHidden={ false }
eventPrefix={ '' }
displayProgressHeader={ false }
keepCompletedTaskList="no"
isVisible={ true }
/>
);
expect( queryByText( dismissedTask[ 0 ].title ) ).toBeInTheDocument();
} );
} );

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Cleanup and deprecate unused Task properties and methods

View File

@ -5,13 +5,7 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;
use \Automattic\WooCommerce\Internal\Admin\Loader;
use Automattic\WooCommerce\Admin\API\Reports\Taxes\Stats\DataStore as TaxDataStore;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\DeprecatedOptions;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Appearance;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Products;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\Tax;
use Automattic\WooCommerce\Admin\PluginsHelper;
/**
* Contains the logic for completing onboarding tasks.

View File

@ -27,6 +27,8 @@ abstract class Task {
* Name of the snooze option.
*
* @var string
*
* @deprecated 7.2.0
*/
const SNOOZED_OPTION = 'woocommerce_task_list_remind_me_later_tasks';
@ -178,9 +180,13 @@ abstract class Task {
/**
* Level.
*
* @deprecated 7.2.0
*
* @return string
*/
public function get_level() {
wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );
return 3;
}
@ -267,18 +273,26 @@ abstract class Task {
/**
* Check if a task is snoozeable.
*
* @deprecated 7.2.0
*
* @return bool
*/
public function is_snoozeable() {
wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );
return false;
}
/**
* Get the snoozed until datetime.
*
* @deprecated 7.2.0
*
* @return string
*/
public function get_snoozed_until() {
wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );
$snoozed_tasks = get_option( self::SNOOZED_OPTION, array() );
if ( isset( $snoozed_tasks[ $this->get_id() ] ) ) {
return $snoozed_tasks[ $this->get_id() ];
@ -290,9 +304,13 @@ abstract class Task {
/**
* Bool for task snoozed.
*
* @deprecated 7.2.0
*
* @return bool
*/
public function is_snoozed() {
wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );
if ( ! $this->is_snoozeable() ) {
return false;
}
@ -306,9 +324,14 @@ abstract class Task {
* Snooze the task.
*
* @param string $duration Duration to snooze. day|hour|week.
*
* @deprecated 7.2.0
*
* @return bool
*/
public function snooze( $duration = 'day' ) {
wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );
if ( ! $this->is_snoozeable() ) {
return false;
}
@ -330,9 +353,13 @@ abstract class Task {
/**
* Undo task snooze.
*
* @deprecated 7.2.0
*
* @return bool
*/
public function undo_snooze() {
wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );
$snoozed = get_option( self::SNOOZED_OPTION, array() );
unset( $snoozed[ $this->get_id() ] );
$update = update_option( self::SNOOZED_OPTION, $snoozed );
@ -406,9 +433,13 @@ abstract class Task {
/**
* Check if task is disabled.
*
* @deprecated 7.2.0
*
* @return bool
*/
public function is_disabled() {
wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );
return false;
}
@ -453,15 +484,15 @@ abstract class Task {
'actionUrl' => $this->get_action_url(),
'isComplete' => $this->is_complete(),
'time' => $this->get_time(),
'level' => $this->get_level(),
'level' => 3,
'isActioned' => $this->is_actioned(),
'isDismissed' => $this->is_dismissed(),
'isDismissable' => $this->is_dismissable(),
'isSnoozed' => $this->is_snoozed(),
'isSnoozeable' => $this->is_snoozeable(),
'isSnoozed' => false,
'isSnoozeable' => false,
'isVisited' => $this->is_visited(),
'isDisabled' => $this->is_disabled(),
'snoozedUntil' => $this->get_snoozed_until(),
'isDisabled' => false,
'snoozedUntil' => null,
'additionalData' => self::convert_object_to_camelcase( $this->get_additional_data() ),
'eventPrefix' => $this->prefix_event( '' ),
);

View File

@ -99,6 +99,8 @@ class TaskList {
/**
* Array of TaskListSection.
*
* @deprecated 7.2.0
*
* @var array
*/
private $sections = array();
@ -106,6 +108,8 @@ class TaskList {
/**
* Key value map of task class and id used for sections.
*
* @deprecated 7.2.0
*
* @var array
*/
public $task_class_id_map = array();
@ -126,7 +130,6 @@ class TaskList {
'options' => array(),
'visible' => true,
'display_progress_header' => false,
'sections' => array(),
);
$data = wp_parse_args( $data, $defaults );
@ -147,12 +150,6 @@ class TaskList {
}
$this->possibly_remove_reminder_bar();
$this->sections = array_map(
function( $section ) {
return new TaskListSection( $section, $this );
},
$data['sections']
);
}
/**
@ -274,9 +271,7 @@ class TaskList {
return;
}
$task_class_name = substr( get_class( $task ), strrpos( get_class( $task ), '\\' ) + 1 );
$this->task_class_id_map[ $task_class_name ] = $task->get_id();
$this->tasks[] = $task;
$this->tasks[] = $task;
}
/**
@ -315,9 +310,13 @@ class TaskList {
/**
* Get task list sections.
*
* @deprecated 7.2.0
*
* @return array
*/
public function get_sections() {
wc_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '7.2.0' );
return $this->sections;
}
@ -420,12 +419,6 @@ class TaskList {
'eventPrefix' => $this->prefix_event( '' ),
'displayProgressHeader' => $this->display_progress_header,
'keepCompletedTaskList' => $this->get_keep_completed_task_list(),
'sections' => array_map(
function( $section ) {
return $section->get_json();
},
$this->sections
),
);
}
}

View File

@ -7,6 +7,8 @@ namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks;
/**
* Task List section class.
*
* @deprecated 7.2.0
*/
class TaskListSection {

View File

@ -39,9 +39,6 @@ class Appearance extends Task {
* @return string
*/
public function get_title() {
if ( count( $this->task_list->get_sections() ) > 0 && ! $this->is_complete() ) {
return __( 'Make your store stand out with unique design', 'woocommerce' );
}
if ( $this->get_parent_option( 'use_completed_title' ) === true ) {
if ( $this->is_complete() ) {
return __( 'You personalized your store', 'woocommerce' );
@ -57,9 +54,6 @@ class Appearance extends Task {
* @return string
*/
public function get_content() {
if ( count( $this->task_list->get_sections() ) > 0 ) {
return __( 'Upload your logo to adapt the store to your brands personality.', 'woocommerce' );
}
return __(
'Add your logo, create a homepage, and start designing your store.',
'woocommerce'

View File

@ -25,9 +25,6 @@ class Marketing extends Task {
* @return string
*/
public function get_title() {
if ( count( $this->task_list->get_sections() ) > 0 && ! $this->is_complete() ) {
return __( 'Grow your business with marketing tools', 'woocommerce' );
}
if ( true === $this->get_parent_option( 'use_completed_title' ) ) {
if ( $this->is_complete() ) {
return __( 'You added sales channels', 'woocommerce' );
@ -43,9 +40,6 @@ class Marketing extends Task {
* @return string
*/
public function get_content() {
if ( count( $this->task_list->get_sections() ) > 0 ) {
return __( 'Promote your store in other sales channels, like email, Google, and Facebook.', 'woocommerce' );
}
return __(
'Add recommended marketing tools to reach new customers and grow your business',
'woocommerce'

View File

@ -3,7 +3,6 @@
namespace Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks;
use Automattic\WooCommerce\Admin\Features\Features;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Tasks\WooCommercePayments;
use Automattic\WooCommerce\Admin\Features\OnboardingTasks\Task;
/**
@ -32,9 +31,6 @@ class Payments extends Task {
* @return string
*/
public function get_title() {
if ( count( $this->task_list->get_sections() ) > 0 && ! $this->is_complete() ) {
return __( 'Add a way to get paid', 'woocommerce' );
}
if ( true === $this->get_parent_option( 'use_completed_title' ) ) {
if ( $this->is_complete() ) {
return __( 'You set up payments', 'woocommerce' );
@ -50,9 +46,6 @@ class Payments extends Task {
* @return string
*/
public function get_content() {
if ( count( $this->task_list->get_sections() ) > 0 ) {
return __( 'Let your customers pay the way they like.', 'woocommerce' );
}
return __(
'Choose payment providers and enable payment methods at checkout.',
'woocommerce'

View File

@ -37,9 +37,6 @@ class Products extends Task {
* @return string
*/
public function get_title() {
if ( count( $this->task_list->get_sections() ) > 0 && ! $this->is_complete() ) {
return __( 'Create or upload your first products', 'woocommerce' );
}
if ( $this->get_parent_option( 'use_completed_title' ) === true ) {
if ( $this->is_complete() ) {
return __( 'You added products', 'woocommerce' );
@ -55,9 +52,6 @@ class Products extends Task {
* @return string
*/
public function get_content() {
if ( count( $this->task_list->get_sections() ) > 0 ) {
return __( 'Add products to sell and build your catalog.', 'woocommerce' );
}
return __(
'Start by adding the first product to your store. You can add your products manually, via CSV, or import them from another service.',
'woocommerce'

View File

@ -43,9 +43,6 @@ class Shipping extends Task {
* @return string
*/
public function get_title() {
if ( count( $this->task_list->get_sections() ) > 0 && ! $this->is_complete() ) {
return __( 'Select how to ship your products', 'woocommerce' );
}
if ( true === $this->get_parent_option( 'use_completed_title' ) ) {
if ( $this->is_complete() ) {
return __( 'You added shipping costs', 'woocommerce' );
@ -61,9 +58,6 @@ class Shipping extends Task {
* @return string
*/
public function get_content() {
if ( count( $this->task_list->get_sections() ) > 0 ) {
return __( 'Set delivery costs and enable extra features, like shipping label printing.', 'woocommerce' );
}
return __(
"Set your store location and where you'll ship to.",
'woocommerce'

View File

@ -62,9 +62,6 @@ class Tax extends Task {
* @return string
*/
public function get_title() {
if ( count( $this->task_list->get_sections() ) > 0 && ! $this->is_complete() ) {
return __( 'Get taxes out of your mind', 'woocommerce' );
}
if ( $this->get_parent_option( 'use_completed_title' ) === true ) {
if ( $this->is_complete() ) {
return __( 'You added tax rates', 'woocommerce' );
@ -80,9 +77,6 @@ class Tax extends Task {
* @return string
*/
public function get_content() {
if ( count( $this->task_list->get_sections() ) > 0 ) {
return __( 'Have sales tax calculated automatically, or add the rates manually.', 'woocommerce' );
}
return self::can_use_automated_taxes()
? __(
'Good news! WooCommerce Services and Jetpack can automate your sales tax calculations for you.',

View File

@ -51,7 +51,6 @@ class WC_Admin_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
// Resetting task list options and lists.
update_option( Task::DISMISSED_OPTION, array() );
update_option( Task::SNOOZED_OPTION, array() );
TaskLists::clear_lists();
}
@ -185,185 +184,6 @@ class WC_Admin_Tests_API_Onboarding_Tasks extends WC_REST_Unit_Test_Case {
$this->assertSame( 'Custom post content', get_the_content( null, null, $data['post_id'] ) );
}
/**
* Test that a task can be snoozed.
* @group tasklist
*/
public function test_task_can_be_snoozed() {
wp_set_current_user( $this->user );
TaskLists::add_list(
array(
'id' => 'test-list',
)
);
TaskLists::add_task(
'test-list',
new TestTask(
TaskLists::get_list( 'test-list' ),
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_snoozeable' => true,
)
)
);
$request = new WP_REST_Request( 'POST', $this->endpoint . '/test-task/snooze' );
$request->set_headers( array( 'content-type' => 'application/json' ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$task = TaskLists::get_task( 'test-task' );
$this->assertEquals( $data['isSnoozed'], true );
$this->assertEquals( isset( $data['snoozedUntil'] ), true );
$this->assertEquals( $task->is_snoozed(), true );
$this->assertNotNull( $task->get_snoozed_until() );
}
/**
* Test that a task can be snoozed with determined list ID.
* @group tasklist
*/
public function test_task_can_be_snoozed_with_list_id() {
wp_set_current_user( $this->user );
TaskLists::add_list(
array(
'id' => 'test-list',
)
);
TaskLists::add_task(
'test-list',
new TestTask(
TaskLists::get_list( 'test-list' ),
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_snoozeable' => true,
)
)
);
$request = new WP_REST_Request( 'POST', $this->endpoint . '/test-task/snooze' );
$request->set_headers( array( 'content-type' => 'application/json' ) );
$request->set_body( wp_json_encode( array( 'task_list_id' => 'test-list' ) ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$task = TaskLists::get_task( 'test-task' );
$this->assertEquals( $data['isSnoozed'], true );
$this->assertEquals( isset( $data['snoozedUntil'] ), true );
$this->assertEquals( $task->is_snoozed(), true );
$this->assertNotNull( $task->get_snoozed_until() );
}
/**
* Test that a task can be snoozed with determined duration.
* @group tasklist
*/
public function test_task_can_be_snoozed_with_duration() {
wp_set_current_user( $this->user );
TaskLists::add_list(
array(
'id' => 'test-list',
)
);
TaskLists::add_task(
'test-list',
new TestTask(
TaskLists::get_list( 'test-list' ),
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_snoozeable' => true,
)
)
);
$request = new WP_REST_Request( 'POST', $this->endpoint . '/test-task/snooze' );
$request->set_headers( array( 'content-type' => 'application/json' ) );
$request->set_body( wp_json_encode( array( 'duration' => 'week' ) ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$task = TaskLists::get_task( 'test-task' );
$week_in_ms = WEEK_IN_SECONDS * 1000;
// Taking off 1 minute as matching a week is very precise and we might run into some race conditions otherwise.
$week_in_ms -= MINUTE_IN_SECONDS * 1000;
$this->assertEquals( $data['snoozedUntil'] >= ( ( time() * 1000 ) + $week_in_ms ), true );
}
/**
* Test that a snoozed task can be undone.
* @group tasklist
*/
public function test_snoozed_task_can_be_undone() {
wp_set_current_user( $this->user );
TaskLists::add_list(
array(
'id' => 'test-list',
)
);
TaskLists::add_task(
'test-list',
new TestTask(
TaskLists::get_list( 'test-list' ),
array(
'id' => 'test-task',
'title' => 'Test Task',
'is_snoozeable' => true,
)
)
);
$task = TaskLists::get_task( 'test-task' );
$task->snooze();
$this->assertEquals( $task->is_snoozed(), true );
$request = new WP_REST_Request( 'POST', $this->endpoint . '/test-task/undo_snooze' );
$request->set_headers( array( 'content-type' => 'application/json' ) );
$response = $this->server->dispatch( $request );
$data = $response->get_data();
$task_after_request = TaskLists::get_task( 'test-task' );
$this->assertEquals( $task_after_request->is_snoozed(), false );
}
/**
* Test that snooze endpoint returns error for invalid task.
* @group tasklist
*/
public function test_snoozed_task_invalid() {
$this->markTestSkipped( 'Skipped temporarily due to change in endpoint behavior.' );
wp_set_current_user( $this->user );
$request = new WP_REST_Request( 'POST', $this->endpoint . '/test-task/snooze' );
$request->set_headers( array( 'content-type' => 'application/json' ) );
$response = $this->server->dispatch( $request );
$response_data = $response->get_data();
$this->assertEquals( $response_data['data']['status'], 404 );
$this->assertEquals( $response_data['code'], 'woocommerce_rest_invalid_task' );
}
/**
* Test that a task can be dismissed.
* @group tasklist

View File

@ -99,100 +99,6 @@ class WC_Admin_Tests_OnboardingTasks_Task extends WC_Unit_Test_Case {
}
/**
* Tests that a task can be snoozed.
*/
public function test_snooze() {
$task = new TestTask(
new TaskList( array( 'id' => 'setup' ) ),
array(
'id' => 'wc-unit-test-snoozeable-task',
'is_snoozeable' => true,
)
);
$update = $task->snooze();
$snoozed = get_option( Task::SNOOZED_OPTION, array() );
$this->assertEquals( true, $update );
$this->assertArrayHasKey( $task->get_id(), $snoozed );
}
/**
* Tests that a task can be unsnoozed.
*/
public function test_undo_snooze() {
$task = new TestTask(
new TaskList( array( 'id' => 'setup' ) ),
array(
'id' => 'wc-unit-test-snoozeable-task',
'is_snoozeable' => true,
)
);
$task->snooze();
$task->undo_snooze();
$snoozed = get_option( Task::SNOOZED_OPTION, array() );
$this->assertArrayNotHasKey( $task->get_id(), $snoozed );
}
/**
* Tests that a task's snooze time is automatically added.
*/
public function test_snoozed_until() {
$time = time() * 1000;
$snoozed = get_option( Task::SNOOZED_OPTION, array() );
$snoozed['wc-unit-test-task'] = $time;
update_option( Task::SNOOZED_OPTION, $snoozed );
$task = new TestTask(
new TaskList( array( 'id' => 'setup' ) ),
array(
'id' => 'wc-unit-test-task',
'is_snoozeable' => true,
)
);
$this->assertEquals( $time, $task->get_snoozed_until() );
}
/**
* Tests that a non snoozeable task cannot be snoozed.
*/
public function test_not_snoozeable() {
$task = new TestTask(
new TaskList( array( 'id' => 'setup' ) ),
array(
'id' => 'wc-unit-test-snoozeable-task',
'is_snoozeable' => false,
)
);
$task->snooze();
$this->assertEquals( false, $task->is_snoozed() );
}
/**
* Tests that a task is no longer consider snoozed after the time has passed.
*/
public function test_snooze_time() {
$task = new TestTask(
new TaskList( array( 'id' => 'setup' ) ),
array(
'id' => 'wc-unit-test-snoozeable-task',
'is_snoozeable' => true,
)
);
$time = time() * 1000 - 1;
$snoozed = get_option( Task::SNOOZED_OPTION, array() );
$snoozed['wc-unit-test-snoozeable-task'] = $time;
update_option( Task::SNOOZED_OPTION, $snoozed );
$this->assertEquals( false, $task->is_snoozed() );
}
/**
* Tests that a task's properties are returned as JSON.
*/