fix: lys hub show only incompleted and recent tasks (#46190)
* fix: lys hub show only incompleted and recent tasks * disable completed task items * Update plugins/woocommerce-admin/client/launch-your-store/hub/sidebar/tasklist.tsx Co-authored-by: Ilyas Foo <foo.ilyas@gmail.com> * strikethrough font color --------- Co-authored-by: Ilyas Foo <foo.ilyas@gmail.com>
This commit is contained in:
parent
3f601b3f45
commit
34b48892e0
|
@ -25,8 +25,9 @@ import {
|
|||
*/
|
||||
import type { SidebarComponentProps } from '../xstate';
|
||||
import { SidebarContainer } from './sidebar-container';
|
||||
import { taskCompleteIcon, taskIcons } from './icons';
|
||||
import { taskCompleteIcon } from './icons';
|
||||
import { SiteHub } from '~/customize-store/assembler-hub/site-hub';
|
||||
import { CompletedTaskItem, IncompleteTaskItem } from '../tasklist';
|
||||
export const LaunchYourStoreHubSidebar: React.FC< SidebarComponentProps > = (
|
||||
props
|
||||
) => {
|
||||
|
@ -109,28 +110,25 @@ export const LaunchYourStoreHubSidebar: React.FC< SidebarComponentProps > = (
|
|||
<ItemGroup className="edit-site-sidebar-navigation-screen-essential-tasks__group">
|
||||
{ tasklist &&
|
||||
hasIncompleteTasks &&
|
||||
tasklist.tasks.map( ( task ) => (
|
||||
<SidebarNavigationItem
|
||||
className={ classnames( task.id, {
|
||||
'is-complete': task.isComplete,
|
||||
} ) }
|
||||
icon={
|
||||
task.isComplete
|
||||
? taskCompleteIcon
|
||||
: taskIcons[ task.id ]
|
||||
}
|
||||
withChevron
|
||||
key={ task.id }
|
||||
onClick={ () => {
|
||||
props.sendEventToSidebar( {
|
||||
type: 'TASK_CLICKED',
|
||||
task,
|
||||
} );
|
||||
} }
|
||||
>
|
||||
{ task.title }
|
||||
</SidebarNavigationItem>
|
||||
) ) }
|
||||
tasklist.tasks.map( ( task ) =>
|
||||
task.isComplete ? (
|
||||
<CompletedTaskItem
|
||||
task={ task }
|
||||
key={ task.id }
|
||||
/>
|
||||
) : (
|
||||
<IncompleteTaskItem
|
||||
task={ task }
|
||||
key={ task.id }
|
||||
onClick={ () => {
|
||||
props.sendEventToSidebar( {
|
||||
type: 'TASK_CLICKED',
|
||||
task,
|
||||
} );
|
||||
} }
|
||||
/>
|
||||
)
|
||||
) }
|
||||
{ tasklist && ! hasIncompleteTasks && (
|
||||
<SidebarNavigationItem
|
||||
className="all-tasks-complete"
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
/* eslint-disable @woocommerce/dependency-group */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { ONBOARDING_STORE_NAME, TaskType } from '@woocommerce/data';
|
||||
import { navigateTo, getNewPath } from '@woocommerce/navigation';
|
||||
import { resolveSelect } from '@wordpress/data';
|
||||
import { applyFilters } from '@wordpress/hooks';
|
||||
import classnames from 'classnames';
|
||||
// @ts-ignore No types for this exist yet.
|
||||
import SidebarNavigationItem from '@wordpress/edit-site/build-module/components/sidebar-navigation-item';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { createStorageUtils } from '~/utils/localStorage';
|
||||
import { taskCompleteIcon, taskIcons } from './components/icons';
|
||||
|
||||
const SEVEN_DAYS_IN_SECONDS = 60 * 60 * 24 * 7;
|
||||
export const LYS_RECENTLY_ACTIONED_TASKS_KEY = 'lys_recently_actioned_tasks';
|
||||
|
||||
export const {
|
||||
getWithExpiry: getRecentlyActionedTasks,
|
||||
setWithExpiry: saveRecentlyActionedTask,
|
||||
} = createStorageUtils< string[] >(
|
||||
LYS_RECENTLY_ACTIONED_TASKS_KEY,
|
||||
SEVEN_DAYS_IN_SECONDS
|
||||
);
|
||||
|
||||
export const getLysTasklist = async () => {
|
||||
const LYS_TASKS_WHITELIST = [
|
||||
'products',
|
||||
'customize-store',
|
||||
'woocommerce-payments',
|
||||
'payments',
|
||||
'shipping',
|
||||
'tax',
|
||||
];
|
||||
|
||||
/**
|
||||
* This filter allows customizing the list of tasks to show in WooCommerce Launch Your Store feature.
|
||||
*
|
||||
* @filter woocommerce_launch_your_store_tasklist_whitelist
|
||||
* @param {string[]} LYS_TASKS_WHITELIST Default list of task IDs to show in LYS.
|
||||
*
|
||||
*/
|
||||
const filteredTasks = applyFilters(
|
||||
'woocommerce_launch_your_store_tasklist_whitelist',
|
||||
[ ...LYS_TASKS_WHITELIST ]
|
||||
) as string[];
|
||||
|
||||
const tasklist = await resolveSelect(
|
||||
ONBOARDING_STORE_NAME
|
||||
).getTaskListsByIds( [ 'setup' ] );
|
||||
|
||||
const recentlyActionedTasks = getRecentlyActionedTasks() ?? [];
|
||||
|
||||
/**
|
||||
* Show tasks that fulfill all the following conditions:
|
||||
* 1. part of the whitelist of tasks to show in LYS
|
||||
* 2. either not completed or recently actioned
|
||||
*/
|
||||
const visibleTasks = tasklist[ 0 ].tasks.filter(
|
||||
( task ) =>
|
||||
filteredTasks.includes( task.id ) &&
|
||||
( ! task.isComplete || recentlyActionedTasks.includes( task.id ) )
|
||||
);
|
||||
|
||||
return {
|
||||
...tasklist[ 0 ],
|
||||
tasks: visibleTasks,
|
||||
};
|
||||
};
|
||||
|
||||
export function taskClickedAction( event: {
|
||||
type: 'TASK_CLICKED';
|
||||
task: TaskType;
|
||||
} ) {
|
||||
const recentlyActionedTasks = getRecentlyActionedTasks() ?? [];
|
||||
saveRecentlyActionedTask( [ ...recentlyActionedTasks, event.task.id ] );
|
||||
if ( event.task.actionUrl ) {
|
||||
navigateTo( { url: event.task.actionUrl } );
|
||||
} else {
|
||||
navigateTo( {
|
||||
url: getNewPath( { task: event.task.id }, '/', {} ),
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
export const CompletedTaskItem: React.FC< {
|
||||
task: TaskType;
|
||||
classNames?: string;
|
||||
} > = ( { task, classNames } ) => (
|
||||
<SidebarNavigationItem
|
||||
className={ classnames( task.id, 'is-complete', classNames ) }
|
||||
icon={ taskCompleteIcon }
|
||||
disabled={ true }
|
||||
>
|
||||
{ task.title }
|
||||
</SidebarNavigationItem>
|
||||
);
|
||||
|
||||
export const IncompleteTaskItem: React.FC< {
|
||||
task: TaskType;
|
||||
classNames?: string;
|
||||
onClick: () => void;
|
||||
} > = ( { task, classNames, onClick } ) => (
|
||||
<SidebarNavigationItem
|
||||
className={ classnames( task.id, classNames ) }
|
||||
icon={ taskIcons[ task.id ] }
|
||||
withChevron
|
||||
onClick={ onClick }
|
||||
>
|
||||
{ task.title }
|
||||
</SidebarNavigationItem>
|
||||
);
|
|
@ -11,14 +11,8 @@ import {
|
|||
} from 'xstate5';
|
||||
import React from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { getNewPath, getQuery, navigateTo } from '@woocommerce/navigation';
|
||||
import { resolveSelect } from '@wordpress/data';
|
||||
import {
|
||||
ONBOARDING_STORE_NAME,
|
||||
TaskListType,
|
||||
TaskType,
|
||||
} from '@woocommerce/data';
|
||||
import { applyFilters } from '@wordpress/hooks';
|
||||
import { getQuery, navigateTo } from '@woocommerce/navigation';
|
||||
import { TaskListType, TaskType } from '@woocommerce/data';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -27,6 +21,7 @@ import { LaunchYourStoreHubSidebar } from './components/launch-store-hub';
|
|||
import type { LaunchYourStoreComponentProps } from '..';
|
||||
import type { mainContentMachine } from '../main-content/xstate';
|
||||
import { updateQueryParams, createQueryParamsListener } from '../common';
|
||||
import { taskClickedAction, getLysTasklist } from './tasklist';
|
||||
|
||||
export type SidebarMachineContext = {
|
||||
externalUrl: string | null;
|
||||
|
@ -52,31 +47,6 @@ const sidebarQueryParamListener = fromCallback( ( { sendBack } ) => {
|
|||
return createQueryParamsListener( 'sidebar', sendBack );
|
||||
} );
|
||||
|
||||
const getLysTasklist = async () => {
|
||||
const LYS_TASKS = [
|
||||
'products',
|
||||
'customize-store',
|
||||
'woocommerce-payments',
|
||||
'payments',
|
||||
'shipping',
|
||||
'tax',
|
||||
];
|
||||
|
||||
const tasklist = await resolveSelect(
|
||||
ONBOARDING_STORE_NAME
|
||||
).getTaskListsByIds( [ 'setup' ] );
|
||||
const visibleTasks: string[] = applyFilters(
|
||||
'woocommerce_launch_your_store_tasklist_visible',
|
||||
[ ...LYS_TASKS ]
|
||||
) as string[];
|
||||
return {
|
||||
...tasklist[ 0 ],
|
||||
tasks: tasklist[ 0 ].tasks.filter( ( task ) =>
|
||||
visibleTasks.includes( task.id )
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
export const sidebarMachine = setup( {
|
||||
types: {} as {
|
||||
context: SidebarMachineContext;
|
||||
|
@ -107,13 +77,7 @@ export const sidebarMachine = setup( {
|
|||
},
|
||||
taskClicked: ( { event } ) => {
|
||||
if ( event.type === 'TASK_CLICKED' ) {
|
||||
if ( event.task.actionUrl ) {
|
||||
navigateTo( { url: event.task.actionUrl } );
|
||||
} else {
|
||||
navigateTo( {
|
||||
url: getNewPath( { task: event.task.id }, '/', {} ),
|
||||
} );
|
||||
}
|
||||
taskClickedAction( event );
|
||||
}
|
||||
},
|
||||
openWcAdminUrl: ( { event } ) => {
|
||||
|
|
|
@ -242,6 +242,15 @@
|
|||
.edit-site-sidebar-navigation-item.is-complete {
|
||||
text-decoration: line-through;
|
||||
color: $gray-700;
|
||||
|
||||
&:hover {
|
||||
background: transparent;
|
||||
color: $gray-700;
|
||||
}
|
||||
|
||||
.components-flex-block {
|
||||
color: $gray-700;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
type StoredItem< T > = {
|
||||
data: T;
|
||||
expiry: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* This constructor function exists for type safety purposes, so when you create a pair of set/get functions they have the
|
||||
* same type for the value they store/retrieve.
|
||||
*/
|
||||
export function createStorageUtils< T >(
|
||||
key: string,
|
||||
durationInSeconds: number
|
||||
) {
|
||||
return {
|
||||
setWithExpiry: ( value: T ): void => {
|
||||
const now = new Date();
|
||||
const expiry = new Date( now.getTime() + durationInSeconds * 1000 );
|
||||
|
||||
const item: StoredItem< T > = {
|
||||
data: value,
|
||||
expiry: expiry.toISOString(),
|
||||
};
|
||||
|
||||
localStorage.setItem( key, JSON.stringify( item ) );
|
||||
},
|
||||
getWithExpiry: (): T | null => {
|
||||
const itemStr = localStorage.getItem( key );
|
||||
if ( ! itemStr ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const item: StoredItem< T > = JSON.parse( itemStr );
|
||||
const now = new Date();
|
||||
if ( now > new Date( item.expiry ) ) {
|
||||
localStorage.removeItem( key );
|
||||
return null;
|
||||
}
|
||||
return item.data;
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
Significance: patch
|
||||
Type: fix
|
||||
|
||||
Fix the LYS Hub tasklist so that it only shows incomplete tasks and tasks that were recently actioned
|
Loading…
Reference in New Issue