diff --git a/plugins/woocommerce-admin/client/task-lists/fills/products/constants.tsx b/plugins/woocommerce-admin/client/task-lists/fills/products/constants.tsx
index 466f3a8efcb..1dd3bac2ee5 100644
--- a/plugins/woocommerce-admin/client/task-lists/fills/products/constants.tsx
+++ b/plugins/woocommerce-admin/client/task-lists/fills/products/constants.tsx
@@ -6,8 +6,8 @@ import ProductIcon from 'gridicons/dist/product';
import CloudOutlineIcon from 'gridicons/dist/cloud-outline';
import TypesIcon from 'gridicons/dist/types';
import { Icon, chevronRight } from '@wordpress/icons';
-import { addFilter } from '@wordpress/hooks';
import { recordEvent } from '@woocommerce/tracks';
+import { getAdminLink } from '@woocommerce/settings';
/**
* Internal dependencies
@@ -16,6 +16,7 @@ import Link from './icon/link_24px.js';
import Widget from './icon/widgets_24px.js';
import LightBulb from './icon/lightbulb_24px.js';
import PrintfulIcon from './icon/printful.png';
+import Upload from './icon/upload_40px.js';
export const productTypes = Object.freeze( [
{
@@ -90,7 +91,7 @@ export const PrintfulAdvertProductPlacement = {
'Design and easily sell custom print products online with Printful.',
'woocommerce'
),
- className: 'woocommerce-products-list__item-printful-advert',
+ className: 'woocommerce-products-list__item-advert',
before: (
+ { __( 'Are you already selling somewhere else?', 'woocommerce' ) }
+
+ ),
+ content: __( 'Import your products from a CSV file.', 'woocommerce' ),
+ className: 'woocommerce-products-list__item-advert',
+ before: ,
+ after: ,
+ onClick: () => {
+ recordEvent( 'tasklist_add_product', {
+ method: 'import',
+ } );
+ window.location.href = getAdminLink(
+ 'edit.php?post_type=product&page=product_importer&wc_onboarding_active_task=products'
+ );
+ },
+};
+
+export type SponsoredProductPlacementType =
+ | typeof PrintfulAdvertProductPlacement
+ | typeof ImportCSVItem;
export type ProductType =
| ( typeof productTypes )[ number ]
| typeof LoadSampleProductType
- | typeof SponsoredProductPlacementType;
+ | SponsoredProductPlacementType;
export type ProductTypeKey = ProductType[ 'key' ];
export const onboardingProductTypesToSurfaced: Readonly<
@@ -131,13 +155,3 @@ export const SETUP_TASKLIST_PRODUCT_TYPES_FILTER =
export const SETUP_TASKLIST_PRODUCTS_AFTER_FILTER =
'woocommerce_admin_task_products_after';
-
-if ( window.wcAdminFeatures && window.wcAdminFeatures.printful === true ) {
- addFilter(
- SETUP_TASKLIST_PRODUCTS_AFTER_FILTER,
- 'woocommerce/task-lists/products-sponsored-placement',
- ( products ) => {
- return [ ...products, PrintfulAdvertProductPlacement ];
- }
- );
-}
diff --git a/plugins/woocommerce-admin/client/task-lists/fills/products/footer.tsx b/plugins/woocommerce-admin/client/task-lists/fills/products/footer.tsx
deleted file mode 100644
index 98739bf6c5d..00000000000
--- a/plugins/woocommerce-admin/client/task-lists/fills/products/footer.tsx
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * External dependencies
- */
-import { __ } from '@wordpress/i18n';
-import interpolateComponents from '@automattic/interpolate-components';
-import { Text } from '@woocommerce/experimental';
-import { Link } from '@woocommerce/components';
-import { getAdminLink } from '@woocommerce/settings';
-import { recordEvent } from '@woocommerce/tracks';
-
-/**
- * Internal dependencies
- */
-import useRecordCompletionTime from '../use-record-completion-time';
-
-const Footer: React.FC = () => {
- const { recordCompletionTime } = useRecordCompletionTime( 'products' );
-
- return (
-
-
- { __(
- 'Are you already selling somewhere else?',
- 'woocommerce'
- ) }
-
-
- { interpolateComponents( {
- mixedString: __(
- '{{importCSVLink}}Import your products from a CSV file{{/importCSVLink}}.',
- 'woocommerce'
- ),
- components: {
- importCSVLink: (
- {
- recordEvent( 'tasklist_add_product', {
- method: 'import',
- } );
- recordCompletionTime();
- window.location.href = getAdminLink(
- 'edit.php?post_type=product&page=product_importer&wc_onboarding_active_task=products'
- );
- return false;
- } }
- href=""
- type="wc-admin"
- >
- <>>
-
- ),
- },
- } ) }
-
-
- );
-};
-
-export default Footer;
diff --git a/plugins/woocommerce-admin/client/task-lists/fills/products/icon/upload_40px.js b/plugins/woocommerce-admin/client/task-lists/fills/products/icon/upload_40px.js
new file mode 100644
index 00000000000..2724fd73b99
--- /dev/null
+++ b/plugins/woocommerce-admin/client/task-lists/fills/products/icon/upload_40px.js
@@ -0,0 +1,35 @@
+const Upload = () => {
+ return (
+
+ );
+};
+
+export default Upload;
diff --git a/plugins/woocommerce-admin/client/task-lists/fills/products/index.scss b/plugins/woocommerce-admin/client/task-lists/fills/products/index.scss
index 6f966a4c441..9c68a5de2d9 100644
--- a/plugins/woocommerce-admin/client/task-lists/fills/products/index.scss
+++ b/plugins/woocommerce-admin/client/task-lists/fills/products/index.scss
@@ -53,7 +53,18 @@
.woocommerce-products-stack {
max-width: 550px;
- margin-top: 32px;
+ margin-top: 24px;
+
+ &:first-child {
+ margin-top: 32px;
+ }
+ }
+
+ .woocommerce-list__item-before > svg {
+ fill: var(--wp-admin-theme-color);
+ .stroke-admin-theme {
+ stroke: var(--wp-admin-theme-color);
+ }
}
}
diff --git a/plugins/woocommerce-admin/client/task-lists/fills/products/index.tsx b/plugins/woocommerce-admin/client/task-lists/fills/products/index.tsx
index 231ab43a0e9..83b5b9277e8 100644
--- a/plugins/woocommerce-admin/client/task-lists/fills/products/index.tsx
+++ b/plugins/woocommerce-admin/client/task-lists/fills/products/index.tsx
@@ -20,12 +20,15 @@ import { getAdminSetting } from '~/utils/admin-settings';
import { getSurfacedProductTypeKeys, getProductTypes } from './utils';
import useProductTypeListItems from './use-product-types-list-items';
import Stack from './stack';
-import Footer from './footer';
import LoadSampleProductModal from '../components/load-sample-product-modal';
import useLoadSampleProducts from '../components/use-load-sample-products';
import LoadSampleProductConfirmModal from '../components/load-sample-product-confirm-modal';
import useRecordCompletionTime from '../use-record-completion-time';
-import { SETUP_TASKLIST_PRODUCTS_AFTER_FILTER } from './constants';
+import {
+ SETUP_TASKLIST_PRODUCTS_AFTER_FILTER,
+ ImportCSVItem,
+ PrintfulAdvertProductPlacement,
+} from './constants';
const getOnboardingProductType = (): string[] => {
const onboardingData = getAdminSetting( 'onboarding' );
@@ -72,7 +75,7 @@ export const Products = () => {
() =>
productTypes.map( ( productType ) => ( {
...productType,
- onClick: () => {
+ onClick: (): void => {
productType.onClick();
recordCompletionTime();
},
@@ -113,6 +116,27 @@ export const Products = () => {
return surfacedProductTypesAndAppendedProducts;
}, [ surfacedProductTypeKeys, isExpanded, productTypesWithTimeRecord ] );
+ const footerStack = useMemo( () => {
+ const options = [];
+ const importCSVItemWithTimeRecord = {
+ ...ImportCSVItem,
+ onClick: () => {
+ ImportCSVItem.onClick();
+ recordCompletionTime();
+ },
+ };
+
+ options.push( importCSVItemWithTimeRecord );
+
+ if (
+ window.wcAdminFeatures &&
+ window.wcAdminFeatures.printful === true
+ ) {
+ options.push( PrintfulAdvertProductPlacement );
+ }
+ return options;
+ }, [ recordCompletionTime ] );
+
return (
{
setIsExpanded( ! isExpanded );
} }
/>
-
+
{ isLoadingSampleProducts ? (
diff --git a/plugins/woocommerce-admin/client/task-lists/fills/products/stack.scss b/plugins/woocommerce-admin/client/task-lists/fills/products/stack.scss
index 62f07689d3d..13ad6bd76ff 100644
--- a/plugins/woocommerce-admin/client/task-lists/fills/products/stack.scss
+++ b/plugins/woocommerce-admin/client/task-lists/fills/products/stack.scss
@@ -44,7 +44,7 @@
margin-top: 0;
}
- &.woocommerce-products-list__item-printful-advert {
+ &.woocommerce-products-list__item-advert {
.woocommerce-list__item-before {
background: none;
border-radius: 0;
diff --git a/plugins/woocommerce-admin/client/task-lists/fills/products/stack.tsx b/plugins/woocommerce-admin/client/task-lists/fills/products/stack.tsx
index 1ccf5aaa454..d827749d33a 100644
--- a/plugins/woocommerce-admin/client/task-lists/fills/products/stack.tsx
+++ b/plugins/woocommerce-admin/client/task-lists/fills/products/stack.tsx
@@ -15,7 +15,9 @@ import { ProductType } from './constants';
import './stack.scss';
import useRecordCompletionTime from '../use-record-completion-time';
-type StackProps = {
+type StackProps = StackWithLoadSampleBlurb | StackWithoutText;
+
+type StackWithLoadSampleBlurb = {
items: ( ProductType & {
onClick: () => void;
} )[];
@@ -24,9 +26,18 @@ type StackProps = {
isTaskListItemClicked?: boolean;
};
+type StackWithoutText = {
+ items: ( ProductType & {
+ onClick: () => void;
+ } )[];
+ showOtherOptions: false;
+ onClickLoadSampleProduct?: () => void;
+ isTaskListItemClicked?: boolean;
+};
+
const Stack: React.FC< StackProps > = ( {
items,
- onClickLoadSampleProduct,
+ onClickLoadSampleProduct = () => {},
showOtherOptions = true,
isTaskListItemClicked = false,
} ) => {
diff --git a/plugins/woocommerce-admin/client/task-lists/fills/products/test/footer.tsx b/plugins/woocommerce-admin/client/task-lists/fills/products/test/footer.tsx
deleted file mode 100644
index b75e20d3107..00000000000
--- a/plugins/woocommerce-admin/client/task-lists/fills/products/test/footer.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * External dependencies
- */
-import { render } from '@testing-library/react';
-import userEvent from '@testing-library/user-event';
-import { recordEvent } from '@woocommerce/tracks';
-
-jest.mock( '@woocommerce/tracks', () => ( { recordEvent: jest.fn() } ) );
-
-/**
- * Internal dependencies
- */
-import Footer from '../footer';
-
-describe( 'Footer', () => {
- beforeEach( () => {
- ( recordEvent as jest.Mock ).mockClear();
- } );
- it( 'should render footer with one links', () => {
- const { queryAllByRole } = render( );
- expect( queryAllByRole( 'link' ) ).toHaveLength( 1 );
- } );
-
- it( 'clicking on import CSV should fire event tasklist_add_product with method:import and task_completion_time', () => {
- const { getByText } = render( );
- userEvent.click( getByText( 'Import your products from a CSV file' ) );
- expect( recordEvent ).toHaveBeenNthCalledWith(
- 1,
- 'tasklist_add_product',
- { method: 'import' }
- );
- expect( recordEvent ).toHaveBeenNthCalledWith(
- 2,
- 'task_completion_time',
- { task_name: 'products', time: '0-2s' }
- );
- } );
-} );
diff --git a/plugins/woocommerce-admin/client/task-lists/fills/products/test/index.tsx b/plugins/woocommerce-admin/client/task-lists/fills/products/test/index.tsx
index de7d916a5a8..eaf725ef5e1 100644
--- a/plugins/woocommerce-admin/client/task-lists/fills/products/test/index.tsx
+++ b/plugins/woocommerce-admin/client/task-lists/fills/products/test/index.tsx
@@ -72,10 +72,11 @@ describe( 'Products', () => {
product_types: [ 'downloads' ],
},
} ) );
- const { queryByText, queryByRole } = render( );
+ const { queryByText, queryAllByRole } = render( );
+ const productTypeList = queryAllByRole( 'menu' )?.[ 0 ];
expect( queryByText( 'Digital product' ) ).toBeInTheDocument();
- expect( queryByRole( 'menu' )?.childElementCount ).toBe( 1 );
+ expect( productTypeList?.childElementCount ).toBe( 1 );
expect( queryByText( 'View more product types' ) ).toBeInTheDocument();
} );
@@ -116,7 +117,9 @@ describe( 'Products', () => {
product_types: [ 'downloads' ],
},
} ) );
- const { queryByText, getByRole, queryByRole } = render( );
+ const { queryByText, getByRole, queryAllByRole } = render(
+
+ );
expect( queryByText( 'View more product types' ) ).toBeInTheDocument();
@@ -124,11 +127,13 @@ describe( 'Products', () => {
getByRole( 'button', { name: 'View more product types' } )
);
- await waitFor( () =>
- expect( queryByRole( 'menu' )?.childElementCount ).toBe(
+ await waitFor( () => {
+ const productTypeList = queryAllByRole( 'menu' )?.[ 0 ];
+ expect( productTypeList?.childElementCount ).toBe(
productTypes.length
- )
- );
+ );
+ } );
+
userEvent.click(
getByRole( 'menuitem', {
name: 'Grouped product A collection of related products.',
@@ -162,7 +167,9 @@ describe( 'Products', () => {
product_types: [ 'downloads' ],
},
} ) );
- const { queryByText, getByRole, queryByRole } = render( );
+ const { queryByText, getByRole, queryAllByRole } = render(
+
+ );
expect( queryByText( 'View more product types' ) ).toBeInTheDocument();
@@ -170,11 +177,12 @@ describe( 'Products', () => {
getByRole( 'button', { name: 'View more product types' } )
);
- await waitFor( () =>
- expect( queryByRole( 'menu' )?.childElementCount ).toBe(
+ await waitFor( () => {
+ const productTypeList = queryAllByRole( 'menu' )?.[ 0 ];
+ expect( productTypeList?.childElementCount ).toBe(
productTypes.length
- )
- );
+ );
+ } );
expect( queryByText( 'View less product types' ) ).toBeInTheDocument();
} );
@@ -237,8 +245,10 @@ describe( 'Products', () => {
it( 'should render stacked layout', async () => {
const { container } = render( );
+
expect(
container.getElementsByClassName( 'woocommerce-products-stack' )
- ).toHaveLength( 1 );
+ .length
+ ).toBeGreaterThanOrEqual( 1 );
} );
} );
diff --git a/plugins/woocommerce/changelog/update-product-task-stack b/plugins/woocommerce/changelog/update-product-task-stack
new file mode 100644
index 00000000000..adca9aec1ce
--- /dev/null
+++ b/plugins/woocommerce/changelog/update-product-task-stack
@@ -0,0 +1,4 @@
+Significance: patch
+Type: update
+
+Update the footer section in "Add products" task
diff --git a/plugins/woocommerce/client/admin/config/core.json b/plugins/woocommerce/client/admin/config/core.json
index f4a2434de18..b92febb7855 100644
--- a/plugins/woocommerce/client/admin/config/core.json
+++ b/plugins/woocommerce/client/admin/config/core.json
@@ -25,7 +25,7 @@
"remote-inbox-notifications": true,
"remote-free-extensions": true,
"payment-gateway-suggestions": true,
- "printful": false,
+ "printful": true,
"settings": false,
"shipping-label-banner": true,
"subscriptions": true,
diff --git a/plugins/woocommerce/client/admin/config/development.json b/plugins/woocommerce/client/admin/config/development.json
index 366e33eff8d..fe2009e265a 100644
--- a/plugins/woocommerce/client/admin/config/development.json
+++ b/plugins/woocommerce/client/admin/config/development.json
@@ -23,7 +23,7 @@
"payment-gateway-suggestions": true,
"product-pre-publish-modal": false,
"product-custom-fields": true,
- "printful": false,
+ "printful": true,
"remote-inbox-notifications": true,
"remote-free-extensions": true,
"settings": false,