From b6eec1e1bf46d46359862855a5eb617ae5c9ef12 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Tue, 27 Dec 2022 02:05:58 +0800 Subject: [PATCH 01/33] Add introduction banner card to marketing page. --- .../IntroductionBanner.scss | 43 ++++++++++ .../IntroductionBanner/IntroductionBanner.tsx | 86 +++++++++++++++++++ .../IntroductionBanner/illustration.svg | 73 ++++++++++++++++ .../IntroductionBanner/index.ts | 1 + .../IntroductionBanner/woo.svg | 15 ++++ .../MarketingOverviewMultichannel.tsx | 3 + 6 files changed, 221 insertions(+) create mode 100644 plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss create mode 100644 plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx create mode 100644 plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration.svg create mode 100644 plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/index.ts create mode 100644 plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/woo.svg diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss new file mode 100644 index 00000000000..6e72fffa54c --- /dev/null +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss @@ -0,0 +1,43 @@ +.woocommerce-marketing-introduction-banner { + & > div { + display: flex; + } + + .woocommerce-marketing-introduction-banner-content { + width: 350px; + margin: 32px 20px 32px 40px; + + .woocommerce-marketing-introduction-banner-title { + font-size: 20px; + font-weight: 400; + line-height: 28px; + margin-bottom: $gap-smaller; + } + + .woocommerce-marketing-introduction-banner-features { + font-size: 13px; + font-weight: 400; + line-height: 16px; + color: $gray-700; + + svg { + fill: $studio-woocommerce-purple-50; + } + } + } + + .woocommerce-marketing-introduction-banner-illustration { + width: 271px; + background: linear-gradient( + 90deg, + rgba( 247, 237, 247, 0 ) 5.31%, + rgba( 196, 152, 217, 0.12 ) 77.75% + ); + + img { + display: block; + width: 100%; + height: 100%; + } + } +} diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx new file mode 100644 index 00000000000..e56476fa096 --- /dev/null +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx @@ -0,0 +1,86 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Card, Flex, FlexItem, FlexBlock } from '@wordpress/components'; +import { Icon, trendingUp, megaphone } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import './IntroductionBanner.scss'; +import wooIconUrl from './woo.svg'; +import illustrationUrl from './illustration.svg'; + +export const IntroductionBanner = () => { + return ( + +
+
+ { __( + 'Reach new customers and increase sales without leaving WooCommerce', + 'woocommerce' + ) } +
+ + + + + + { __( + 'Reach customers on other sales channels', + 'woocommerce' + ) } + + + + + + + + { __( + 'Advertise with marketing campaigns', + 'woocommerce' + ) } + + + + + + + } + /> + + { __( 'Built by WooCommerce', 'woocommerce' ) } + + + + +
+
+ { +
+
+ ); +}; diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration.svg b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration.svg new file mode 100644 index 00000000000..b2834e68fb8 --- /dev/null +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/index.ts b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/index.ts new file mode 100644 index 00000000000..8ae35a6ca33 --- /dev/null +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/index.ts @@ -0,0 +1 @@ +export { IntroductionBanner } from './IntroductionBanner'; diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/woo.svg b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/woo.svg new file mode 100644 index 00000000000..fb4a4205043 --- /dev/null +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/woo.svg @@ -0,0 +1,15 @@ + + +WooCommerce Logo + + + +image/svg+xml + + + + + + + + diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx index e7858c2c01a..9ac491c34a5 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx @@ -7,6 +7,7 @@ import { useUser } from '@woocommerce/data'; * Internal dependencies */ import { getAdminSetting } from '~/utils/admin-settings'; +import { IntroductionBanner } from './IntroductionBanner'; import { Campaigns } from './Campaigns'; import { Channels } from './Channels'; import { InstalledExtensions } from './InstalledExtensions'; @@ -37,6 +38,8 @@ export const MarketingOverviewMultichannel: React.FC = () => { return (
+ { /* TODO: check wp_options and conditionally display introduction banner. */ } + { dataRegistered.length >= 1 && } { ( dataRegistered.length >= 1 || dataRecommended.length >= 1 ) && ( Date: Tue, 27 Dec 2022 20:47:14 +0800 Subject: [PATCH 02/33] Add close button to introduction banner card. --- .../IntroductionBanner.scss | 7 +++++++ .../IntroductionBanner/IntroductionBanner.tsx | 19 +++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss index 6e72fffa54c..a66d222c477 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss @@ -34,6 +34,13 @@ rgba( 196, 152, 217, 0.12 ) 77.75% ); + .woocommerce-marketing-introduction-banner-close-button { + position: absolute; + top: $gap-smaller; + right: $gap; + padding: 0; + } + img { display: block; width: 100%; diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx index e56476fa096..c8f9377f251 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx @@ -2,8 +2,14 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; -import { Card, Flex, FlexItem, FlexBlock } from '@wordpress/components'; -import { Icon, trendingUp, megaphone } from '@wordpress/icons'; +import { Card, Flex, FlexItem, FlexBlock, Button } from '@wordpress/components'; +import { + Icon, + trendingUp, + megaphone, + closeSmall, + close, +} from '@wordpress/icons'; /** * Internal dependencies @@ -73,6 +79,15 @@ export const IntroductionBanner = () => {
+ { Date: Tue, 27 Dec 2022 21:06:26 +0800 Subject: [PATCH 03/33] Display buttons in introduction banner with large illustration. --- .../IntroductionBanner.scss | 4 + .../IntroductionBanner/IntroductionBanner.tsx | 42 ++++++++--- .../IntroductionBanner/illustration-large.svg | 73 +++++++++++++++++++ .../MarketingOverviewMultichannel.tsx | 2 +- 4 files changed, 111 insertions(+), 10 deletions(-) create mode 100644 plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration-large.svg diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss index a66d222c477..24964da3120 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss @@ -24,6 +24,10 @@ fill: $studio-woocommerce-purple-50; } } + + .woocommerce-marketing-introduction-banner-buttons { + margin-top: $gap; + } } .woocommerce-marketing-introduction-banner-illustration { diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx index c8f9377f251..b53cf96f97d 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx @@ -3,13 +3,7 @@ */ import { __ } from '@wordpress/i18n'; import { Card, Flex, FlexItem, FlexBlock, Button } from '@wordpress/components'; -import { - Icon, - trendingUp, - megaphone, - closeSmall, - close, -} from '@wordpress/icons'; +import { Icon, trendingUp, megaphone, closeSmall } from '@wordpress/icons'; /** * Internal dependencies @@ -17,8 +11,15 @@ import { import './IntroductionBanner.scss'; import wooIconUrl from './woo.svg'; import illustrationUrl from './illustration.svg'; +import illustrationLargeUrl from './illustration-large.svg'; -export const IntroductionBanner = () => { +type IntroductionBannerProps = { + showButtons: boolean; +}; + +export const IntroductionBanner = ( { + showButtons, +}: IntroductionBannerProps ) => { return (
@@ -77,6 +78,29 @@ export const IntroductionBanner = () => { + { showButtons && ( + + + + + ) }
{ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx index 9ac491c34a5..3969ecccee6 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx @@ -39,7 +39,7 @@ export const MarketingOverviewMultichannel: React.FC = () => { return (
{ /* TODO: check wp_options and conditionally display introduction banner. */ } - + = 1 } /> { dataRegistered.length >= 1 && } { ( dataRegistered.length >= 1 || dataRecommended.length >= 1 ) && ( Date: Tue, 27 Dec 2022 22:01:46 +0800 Subject: [PATCH 04/33] Display and dismiss introduction banner with wp_options. --- .../client/marketing/hooks/index.ts | 1 + .../marketing/hooks/useIntroductionBanner.ts | 40 +++++++++++++++++++ .../IntroductionBanner/IntroductionBanner.tsx | 6 +-- .../MarketingOverviewMultichannel.tsx | 20 ++++++++-- 4 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts diff --git a/plugins/woocommerce-admin/client/marketing/hooks/index.ts b/plugins/woocommerce-admin/client/marketing/hooks/index.ts index 0a80d7f7f22..e21457e5485 100644 --- a/plugins/woocommerce-admin/client/marketing/hooks/index.ts +++ b/plugins/woocommerce-admin/client/marketing/hooks/index.ts @@ -1,3 +1,4 @@ +export { useIntroductionBanner } from './useIntroductionBanner'; export { useInstalledPlugins } from './useInstalledPlugins'; export { useRegisteredChannels } from './useRegisteredChannels'; export { useRecommendedChannels } from './useRecommendedChannels'; diff --git a/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts b/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts new file mode 100644 index 00000000000..64facf8279a --- /dev/null +++ b/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts @@ -0,0 +1,40 @@ +/** + * External dependencies + */ +import { useDispatch, useSelect } from '@wordpress/data'; +import { OPTIONS_STORE_NAME } from '@woocommerce/data'; +import { recordEvent } from '@woocommerce/tracks'; + +type UseIntroductionBannerType = { + loading: boolean; + isIntroductionBannerDismissed: boolean; + dismissIntroductionBanner: () => void; +}; + +const OPTION_NAME = + 'woocommerce_marketing_overview_multichannel_banner_dismissed'; +const OPTION_VALUE = 'yes'; + +export const useIntroductionBanner = (): UseIntroductionBannerType => { + const { updateOptions } = useDispatch( OPTIONS_STORE_NAME ); + + const dismissIntroductionBanner = () => { + updateOptions( { + [ OPTION_NAME ]: OPTION_VALUE, + } ); + recordEvent( 'marketing_multichannel_banner_dismissed', {} ); + }; + + return useSelect( ( select ) => { + const { getOption, isOptionsUpdating, hasFinishedResolution } = + select( OPTIONS_STORE_NAME ); + const isUpdateRequesting = isOptionsUpdating(); + + return { + loading: ! hasFinishedResolution( 'getOption', [ OPTION_NAME ] ), + isIntroductionBannerDismissed: + getOption( OPTION_NAME ) === OPTION_VALUE || isUpdateRequesting, + dismissIntroductionBanner, + }; + } ); +}; diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx index b53cf96f97d..73f7ff96b47 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx @@ -15,10 +15,12 @@ import illustrationLargeUrl from './illustration-large.svg'; type IntroductionBannerProps = { showButtons: boolean; + onDismiss: () => void; }; export const IntroductionBanner = ( { showButtons, + onDismiss, }: IntroductionBannerProps ) => { return ( @@ -106,9 +108,7 @@ export const IntroductionBanner = ( { diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx index 3969ecccee6..efce68259e7 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx @@ -15,6 +15,7 @@ import { DiscoverTools } from './DiscoverTools'; import { LearnMarketing } from './LearnMarketing'; import '~/marketing/data'; import { + useIntroductionBanner, useRegisteredChannels, useRecommendedChannels, } from '~/marketing/hooks'; @@ -22,6 +23,11 @@ import './MarketingOverviewMultichannel.scss'; import { CenteredSpinner } from '../components'; export const MarketingOverviewMultichannel: React.FC = () => { + const { + loading: loadingIntroductionBanner, + isIntroductionBannerDismissed, + dismissIntroductionBanner, + } = useIntroductionBanner(); const { loading: loadingRegistered, data: dataRegistered } = useRegisteredChannels(); const { loading: loadingRecommended, data: dataRecommended } = @@ -32,14 +38,22 @@ export const MarketingOverviewMultichannel: React.FC = () => { getAdminSetting( 'allowMarketplaceSuggestions', false ) && currentUserCan( 'install_plugins' ); - if ( loadingRegistered || loadingRecommended ) { + if ( + loadingIntroductionBanner || + loadingRegistered || + loadingRecommended + ) { return ; } return (
- { /* TODO: check wp_options and conditionally display introduction banner. */ } - = 1 } /> + { ! isIntroductionBannerDismissed && ( + = 1 } + onDismiss={ dismissIntroductionBanner } + /> + ) } { dataRegistered.length >= 1 && } { ( dataRegistered.length >= 1 || dataRecommended.length >= 1 ) && ( Date: Tue, 27 Dec 2022 22:13:21 +0800 Subject: [PATCH 05/33] Rename UseIntroductionBannerType to UseIntroductionBanner. --- .../client/marketing/hooks/useIntroductionBanner.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts b/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts index 64facf8279a..4d565afbe2f 100644 --- a/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts +++ b/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts @@ -5,7 +5,7 @@ import { useDispatch, useSelect } from '@wordpress/data'; import { OPTIONS_STORE_NAME } from '@woocommerce/data'; import { recordEvent } from '@woocommerce/tracks'; -type UseIntroductionBannerType = { +type UseIntroductionBanner = { loading: boolean; isIntroductionBannerDismissed: boolean; dismissIntroductionBanner: () => void; @@ -15,7 +15,7 @@ const OPTION_NAME = 'woocommerce_marketing_overview_multichannel_banner_dismissed'; const OPTION_VALUE = 'yes'; -export const useIntroductionBanner = (): UseIntroductionBannerType => { +export const useIntroductionBanner = (): UseIntroductionBanner => { const { updateOptions } = useDispatch( OPTIONS_STORE_NAME ); const dismissIntroductionBanner = () => { From 86cc1181bf1d174ed6604ec8d17b61d6887617f8 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Wed, 28 Dec 2022 00:56:59 +0800 Subject: [PATCH 06/33] Focus on Add Channels section when users click on Add Channels button. --- .../Channels/RecommendedChannels.tsx | 17 ++++++++++++- .../IntroductionBanner/IntroductionBanner.tsx | 8 ++----- .../MarketingOverviewMultichannel.tsx | 24 ++++++++++++++----- .../overview-multichannel/constants.ts | 2 ++ 4 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 plugins/woocommerce-admin/client/marketing/overview-multichannel/constants.ts diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/RecommendedChannels.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/RecommendedChannels.tsx index 94bdd0bf557..6805796f518 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/RecommendedChannels.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/RecommendedChannels.tsx @@ -1,15 +1,20 @@ /** * External dependencies */ -import { useState } from '@wordpress/element'; +import { useState, useEffect, useRef } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { CardBody, CardDivider, Button, Icon } from '@wordpress/components'; import { chevronUp, chevronDown } from '@wordpress/icons'; +import { useLocation } from 'react-router-dom'; /** * Internal dependencies */ import { RecommendedChannel } from '~/marketing/types'; +import { + idAddChannels, + hashAddChannels, +} from '~/marketing/overview-multichannel/constants'; import { RecommendedChannelsList } from './RecommendedChannelsList'; import './RecommendedChannels.scss'; @@ -21,12 +26,22 @@ export const RecommendedChannels: React.FC< RecommendedChannelsType > = ( { recommendedChannels, } ) => { const [ collapsed, setCollapsed ] = useState( true ); + const buttonRef = useRef< HTMLAnchorElement >( null ); + const location = useLocation(); + + useEffect( () => { + if ( buttonRef.current && location.hash === hashAddChannels ) { + buttonRef.current.focus(); + } + }, [ location.hash ] ); return (
- diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx index efce68259e7..625c7359b3b 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx @@ -2,6 +2,8 @@ * External dependencies */ import { useUser } from '@woocommerce/data'; +import { ScrollTo } from '@woocommerce/components'; +import { useLocation } from 'react-router-dom'; /** * Internal dependencies @@ -19,6 +21,7 @@ import { useRegisteredChannels, useRecommendedChannels, } from '~/marketing/hooks'; +import { hashAddChannels } from '~/marketing/overview-multichannel/constants'; import './MarketingOverviewMultichannel.scss'; import { CenteredSpinner } from '../components'; @@ -32,6 +35,7 @@ export const MarketingOverviewMultichannel: React.FC = () => { useRegisteredChannels(); const { loading: loadingRecommended, data: dataRecommended } = useRecommendedChannels(); + const location = useLocation(); const { currentUserCan } = useUser(); const shouldShowExtensions = @@ -55,12 +59,20 @@ export const MarketingOverviewMultichannel: React.FC = () => { /> ) } { dataRegistered.length >= 1 && } - { ( dataRegistered.length >= 1 || dataRecommended.length >= 1 ) && ( - - ) } + { ( dataRegistered.length >= 1 || dataRecommended.length >= 1 ) && + ( location.hash === hashAddChannels ? ( + + + + ) : ( + + ) ) } { shouldShowExtensions && } diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/constants.ts b/plugins/woocommerce-admin/client/marketing/overview-multichannel/constants.ts new file mode 100644 index 00000000000..634d591ae98 --- /dev/null +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/constants.ts @@ -0,0 +1,2 @@ +export const idAddChannels = 'add-channels'; +export const hashAddChannels = `#${ idAddChannels }`; From f92f4d3deeadc61b45c63556a9b1fd1b5c70f5ae Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Wed, 28 Dec 2022 01:09:37 +0800 Subject: [PATCH 07/33] Code refactor with useIsLocationHashAddChannels. --- .../client/marketing/hooks/index.ts | 1 + .../hooks/useIsLocationHashAddChannels.ts | 15 +++++++++++++++ .../Channels/RecommendedChannels.tsx | 13 +++++-------- .../MarketingOverviewMultichannel.tsx | 7 +++---- 4 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 plugins/woocommerce-admin/client/marketing/hooks/useIsLocationHashAddChannels.ts diff --git a/plugins/woocommerce-admin/client/marketing/hooks/index.ts b/plugins/woocommerce-admin/client/marketing/hooks/index.ts index e21457e5485..322902f78d1 100644 --- a/plugins/woocommerce-admin/client/marketing/hooks/index.ts +++ b/plugins/woocommerce-admin/client/marketing/hooks/index.ts @@ -2,3 +2,4 @@ export { useIntroductionBanner } from './useIntroductionBanner'; export { useInstalledPlugins } from './useInstalledPlugins'; export { useRegisteredChannels } from './useRegisteredChannels'; export { useRecommendedChannels } from './useRecommendedChannels'; +export { useIsLocationHashAddChannels } from './useIsLocationHashAddChannels'; diff --git a/plugins/woocommerce-admin/client/marketing/hooks/useIsLocationHashAddChannels.ts b/plugins/woocommerce-admin/client/marketing/hooks/useIsLocationHashAddChannels.ts new file mode 100644 index 00000000000..cd87b2995d3 --- /dev/null +++ b/plugins/woocommerce-admin/client/marketing/hooks/useIsLocationHashAddChannels.ts @@ -0,0 +1,15 @@ +/** + * External dependencies + */ +import { useLocation } from 'react-router-dom'; + +/** + * Internal dependencies + */ +import { hashAddChannels } from '~/marketing/overview-multichannel/constants'; + +export const useIsLocationHashAddChannels = () => { + const location = useLocation(); + + return location.hash === hashAddChannels; +}; diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/RecommendedChannels.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/RecommendedChannels.tsx index 6805796f518..bd2710ddfc1 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/RecommendedChannels.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/RecommendedChannels.tsx @@ -5,16 +5,13 @@ import { useState, useEffect, useRef } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { CardBody, CardDivider, Button, Icon } from '@wordpress/components'; import { chevronUp, chevronDown } from '@wordpress/icons'; -import { useLocation } from 'react-router-dom'; /** * Internal dependencies */ +import { useIsLocationHashAddChannels } from '~/marketing/hooks'; import { RecommendedChannel } from '~/marketing/types'; -import { - idAddChannels, - hashAddChannels, -} from '~/marketing/overview-multichannel/constants'; +import { idAddChannels } from '~/marketing/overview-multichannel/constants'; import { RecommendedChannelsList } from './RecommendedChannelsList'; import './RecommendedChannels.scss'; @@ -27,13 +24,13 @@ export const RecommendedChannels: React.FC< RecommendedChannelsType > = ( { } ) => { const [ collapsed, setCollapsed ] = useState( true ); const buttonRef = useRef< HTMLAnchorElement >( null ); - const location = useLocation(); + const isLocationHashAddChannels = useIsLocationHashAddChannels(); useEffect( () => { - if ( buttonRef.current && location.hash === hashAddChannels ) { + if ( buttonRef.current && isLocationHashAddChannels ) { buttonRef.current.focus(); } - }, [ location.hash ] ); + }, [ isLocationHashAddChannels ] ); return (
diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx index 625c7359b3b..758aaf05bf1 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx @@ -3,7 +3,6 @@ */ import { useUser } from '@woocommerce/data'; import { ScrollTo } from '@woocommerce/components'; -import { useLocation } from 'react-router-dom'; /** * Internal dependencies @@ -20,8 +19,8 @@ import { useIntroductionBanner, useRegisteredChannels, useRecommendedChannels, + useIsLocationHashAddChannels, } from '~/marketing/hooks'; -import { hashAddChannels } from '~/marketing/overview-multichannel/constants'; import './MarketingOverviewMultichannel.scss'; import { CenteredSpinner } from '../components'; @@ -35,7 +34,7 @@ export const MarketingOverviewMultichannel: React.FC = () => { useRegisteredChannels(); const { loading: loadingRecommended, data: dataRecommended } = useRecommendedChannels(); - const location = useLocation(); + const isLocationHashAddChannels = useIsLocationHashAddChannels(); const { currentUserCan } = useUser(); const shouldShowExtensions = @@ -60,7 +59,7 @@ export const MarketingOverviewMultichannel: React.FC = () => { ) } { dataRegistered.length >= 1 && } { ( dataRegistered.length >= 1 || dataRecommended.length >= 1 ) && - ( location.hash === hashAddChannels ? ( + ( isLocationHashAddChannels ? ( Date: Wed, 8 Mar 2023 00:34:09 +0800 Subject: [PATCH 08/33] Move CreateNewCampaignModal to shared components folder. --- .../CreateNewCampaignModal/CreateNewCampaignModal.scss | 0 .../CreateNewCampaignModal/CreateNewCampaignModal.test.tsx | 0 .../CreateNewCampaignModal/CreateNewCampaignModal.tsx | 0 .../CreateNewCampaignModal/index.ts | 0 .../woocommerce-admin/client/marketing/components/index.js | 1 + .../marketing/overview-multichannel/Campaigns/Campaigns.tsx | 6 ++++-- 6 files changed, 5 insertions(+), 2 deletions(-) rename plugins/woocommerce-admin/client/marketing/{overview-multichannel/Campaigns => components}/CreateNewCampaignModal/CreateNewCampaignModal.scss (100%) rename plugins/woocommerce-admin/client/marketing/{overview-multichannel/Campaigns => components}/CreateNewCampaignModal/CreateNewCampaignModal.test.tsx (100%) rename plugins/woocommerce-admin/client/marketing/{overview-multichannel/Campaigns => components}/CreateNewCampaignModal/CreateNewCampaignModal.tsx (100%) rename plugins/woocommerce-admin/client/marketing/{overview-multichannel/Campaigns => components}/CreateNewCampaignModal/index.ts (100%) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/CreateNewCampaignModal/CreateNewCampaignModal.scss b/plugins/woocommerce-admin/client/marketing/components/CreateNewCampaignModal/CreateNewCampaignModal.scss similarity index 100% rename from plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/CreateNewCampaignModal/CreateNewCampaignModal.scss rename to plugins/woocommerce-admin/client/marketing/components/CreateNewCampaignModal/CreateNewCampaignModal.scss diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/CreateNewCampaignModal/CreateNewCampaignModal.test.tsx b/plugins/woocommerce-admin/client/marketing/components/CreateNewCampaignModal/CreateNewCampaignModal.test.tsx similarity index 100% rename from plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/CreateNewCampaignModal/CreateNewCampaignModal.test.tsx rename to plugins/woocommerce-admin/client/marketing/components/CreateNewCampaignModal/CreateNewCampaignModal.test.tsx diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/CreateNewCampaignModal/CreateNewCampaignModal.tsx b/plugins/woocommerce-admin/client/marketing/components/CreateNewCampaignModal/CreateNewCampaignModal.tsx similarity index 100% rename from plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/CreateNewCampaignModal/CreateNewCampaignModal.tsx rename to plugins/woocommerce-admin/client/marketing/components/CreateNewCampaignModal/CreateNewCampaignModal.tsx diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/CreateNewCampaignModal/index.ts b/plugins/woocommerce-admin/client/marketing/components/CreateNewCampaignModal/index.ts similarity index 100% rename from plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/CreateNewCampaignModal/index.ts rename to plugins/woocommerce-admin/client/marketing/components/CreateNewCampaignModal/index.ts diff --git a/plugins/woocommerce-admin/client/marketing/components/index.js b/plugins/woocommerce-admin/client/marketing/components/index.js index dc971c75160..5d1c1014754 100644 --- a/plugins/woocommerce-admin/client/marketing/components/index.js +++ b/plugins/woocommerce-admin/client/marketing/components/index.js @@ -8,3 +8,4 @@ export { PluginCardBody, SmartPluginCardBody } from './PluginCardBody'; export { CardHeaderTitle } from './CardHeaderTitle'; export { CardHeaderDescription } from './CardHeaderDescription'; export { CenteredSpinner } from './CenteredSpinner'; +export { CreateNewCampaignModal } from './CreateNewCampaignModal'; diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.tsx index 8eb8ba8b471..0474f85d016 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.tsx @@ -24,10 +24,12 @@ import { /** * Internal dependencies */ -import { CardHeaderTitle } from '~/marketing/components'; +import { + CardHeaderTitle, + CreateNewCampaignModal, +} from '~/marketing/components'; import { useNewCampaignTypes } from '~/marketing/hooks'; import { useCampaigns } from './useCampaigns'; -import { CreateNewCampaignModal } from './CreateNewCampaignModal'; import './Campaigns.scss'; const tableCaption = __( 'Campaigns', 'woocommerce' ); From 0cb2fb1cd0796f39284c21c188a93d3140669e18 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Wed, 8 Mar 2023 00:37:55 +0800 Subject: [PATCH 09/33] Display CreateNewCampaignModal upon button click in IntroductionBanner. --- .../IntroductionBanner/IntroductionBanner.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx index e906e8d40b7..fc288855441 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx @@ -2,12 +2,14 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; +import { useState } from '@wordpress/element'; import { Card, Flex, FlexItem, FlexBlock, Button } from '@wordpress/components'; import { Icon, trendingUp, megaphone, closeSmall } from '@wordpress/icons'; /** * Internal dependencies */ +import { CreateNewCampaignModal } from '~/marketing/components'; import { hashAddChannels } from '~/marketing/overview-multichannel/constants'; import './IntroductionBanner.scss'; import wooIconUrl from './woo.svg'; @@ -23,6 +25,8 @@ export const IntroductionBanner = ( { showButtons, onDismiss, }: IntroductionBannerProps ) => { + const [ open, setOpen ] = useState( false ); + return (
@@ -89,7 +93,7 @@ export const IntroductionBanner = ( { ) } + { open && ( + setOpen( false ) } + /> + ) }
- diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx index 496ec9df5f2..f2510f0e9ba 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx @@ -1,8 +1,8 @@ /** * External dependencies */ +import { useRef } from '@wordpress/element'; import { useUser } from '@woocommerce/data'; -import { ScrollTo } from '@woocommerce/components'; /** * Internal dependencies @@ -14,7 +14,6 @@ import { useIntroductionBanner, useRegisteredChannels, useRecommendedChannels, - useIsLocationHashAddChannels, } from '~/marketing/hooks'; import { getAdminSetting } from '~/utils/admin-settings'; import { IntroductionBanner } from './IntroductionBanner'; @@ -38,8 +37,8 @@ export const MarketingOverviewMultichannel: React.FC = () => { } = useRegisteredChannels(); const { loading: loadingRecommended, data: dataRecommended } = useRecommendedChannels(); - const isLocationHashAddChannels = useIsLocationHashAddChannels(); const { currentUserCan } = useUser(); + const addChannelsButtonRef = useRef< HTMLButtonElement >( null ); const shouldShowExtensions = getAdminSetting( 'allowMarketplaceSuggestions', false ) && @@ -61,27 +60,24 @@ export const MarketingOverviewMultichannel: React.FC = () => { !! dataRegistered && dataRegistered.length >= 1 } onDismiss={ dismissIntroductionBanner } + onAddChannels={ () => { + addChannelsButtonRef.current?.focus(); + addChannelsButtonRef.current?.click(); + addChannelsButtonRef.current?.scrollIntoView(); + } } /> ) } { dataRegistered?.length && } { dataRegistered && dataRecommended && - ( dataRegistered.length || dataRecommended.length ) && - ( isLocationHashAddChannels ? ( - - - - ) : ( + ( dataRegistered.length || dataRecommended.length ) && ( - ) ) } + ) } { shouldShowExtensions && } diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/constants.ts b/plugins/woocommerce-admin/client/marketing/overview-multichannel/constants.ts deleted file mode 100644 index 634d591ae98..00000000000 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const idAddChannels = 'add-channels'; -export const hashAddChannels = `#${ idAddChannels }`; From 42ac7e4d28074e44e61a7b3f659518d79897eeb7 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Wed, 8 Mar 2023 02:54:43 +0800 Subject: [PATCH 11/33] Better logic for displaying buttons in IntroductionBanner. --- .../IntroductionBanner/IntroductionBanner.tsx | 64 ++++++++++++++----- .../MarketingOverviewMultichannel.tsx | 3 - 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx index 9a6740e64c9..4fb9cfef079 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx @@ -10,23 +10,46 @@ import { Icon, trendingUp, megaphone, closeSmall } from '@wordpress/icons'; * Internal dependencies */ import { CreateNewCampaignModal } from '~/marketing/components'; +import { + useRegisteredChannels, + useRecommendedChannels, +} from '~/marketing/hooks'; import './IntroductionBanner.scss'; import wooIconUrl from './woo.svg'; import illustrationUrl from './illustration.svg'; import illustrationLargeUrl from './illustration-large.svg'; type IntroductionBannerProps = { - showButtons: boolean; onDismiss: () => void; onAddChannels: () => void; }; export const IntroductionBanner = ( { - showButtons, onDismiss, onAddChannels, }: IntroductionBannerProps ) => { const [ open, setOpen ] = useState( false ); + const { data: dataRegistered } = useRegisteredChannels(); + const { data: dataRecommended } = useRecommendedChannels(); + + const showCreateCampaignButton = !! dataRegistered?.length; + + /** + * Boolean to display the "Add channels" button in the introduction banner. + * + * This depends on the number of registered channels, + * because if there are no registered channels, + * the Channels card will not have the "Add channels" toggle button, + * and it does not make sense to display the "Add channels" button in this introduction banner + * that will do nothing upon click. + * + * If there are registered channels and recommended channels, + * the Channels card will display the "Add channels" toggle button, + * and clicking on the "Add channels" button in this introduction banner + * will scroll to the button in Channels card. + */ + const showAddChannelsButton = + !! dataRegistered?.length && !! dataRecommended?.length; return ( @@ -86,22 +109,29 @@ export const IntroductionBanner = ( { - { showButtons && ( + { ( showCreateCampaignButton || showAddChannelsButton ) && ( - - + { showCreateCampaignButton && ( + + ) } + { showAddChannelsButton && ( + + ) } ) } { open && ( @@ -119,7 +149,11 @@ export const IntroductionBanner = ( { { {
{ ! isIntroductionBannerDismissed && ( = 1 - } onDismiss={ dismissIntroductionBanner } onAddChannels={ () => { addChannelsButtonRef.current?.focus(); From 1a28784bbe486d781986e47ae3e776d3d05f611b Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Wed, 8 Mar 2023 03:06:05 +0800 Subject: [PATCH 12/33] Add changelog. --- .../changelog/feature-34904-marketing-introduction-banner | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 plugins/woocommerce/changelog/feature-34904-marketing-introduction-banner diff --git a/plugins/woocommerce/changelog/feature-34904-marketing-introduction-banner b/plugins/woocommerce/changelog/feature-34904-marketing-introduction-banner new file mode 100644 index 00000000000..c4f05d3ddb9 --- /dev/null +++ b/plugins/woocommerce/changelog/feature-34904-marketing-introduction-banner @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Add introduction banner to multichannel marketing page. From 66e46d8942126a8d00263d35f985a0a2fa145999 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Thu, 9 Mar 2023 00:34:20 +0800 Subject: [PATCH 13/33] Run lint:css-fix. --- .../IntroductionBanner/IntroductionBanner.scss | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss index 24964da3120..7c46d7887f5 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss @@ -32,11 +32,7 @@ .woocommerce-marketing-introduction-banner-illustration { width: 271px; - background: linear-gradient( - 90deg, - rgba( 247, 237, 247, 0 ) 5.31%, - rgba( 196, 152, 217, 0.12 ) 77.75% - ); + background: linear-gradient(90deg, rgba(247, 237, 247, 0) 5.31%, rgba(196, 152, 217, 0.12) 77.75%); .woocommerce-marketing-introduction-banner-close-button { position: absolute; From 6d72c2bbe13573433f96dfa1df09e0c839e0fc03 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Thu, 9 Mar 2023 01:08:28 +0800 Subject: [PATCH 14/33] Fix failed test for Campaigns component. --- .../Campaigns/Campaigns.test.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.test.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.test.tsx index 4a533f5b9d3..52170ff65d0 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.test.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.test.tsx @@ -19,9 +19,15 @@ jest.mock( '~/marketing/hooks', () => ( { useNewCampaignTypes: jest.fn(), } ) ); -jest.mock( './CreateNewCampaignModal', () => ( { - CreateNewCampaignModal: () =>
Create a new campaign
, -} ) ); +jest.mock( '~/marketing/components', () => { + const originalModule = jest.requireActual( '~/marketing/components' ); + + return { + __esModule: true, + ...originalModule, + CreateNewCampaignModal: () =>
Create a new campaign
, + }; +} ); /** * Create a test campaign data object. From 49253425b213c97b2a855854055a249817b869dc Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Sun, 19 Mar 2023 20:12:09 +0800 Subject: [PATCH 15/33] Specify dependency for useSelect in useIntroductionBanner. Co-authored-by: Eason --- .../client/marketing/hooks/useIntroductionBanner.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts b/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts index 4d565afbe2f..9a4ff91a292 100644 --- a/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts +++ b/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts @@ -36,5 +36,5 @@ export const useIntroductionBanner = (): UseIntroductionBanner => { getOption( OPTION_NAME ) === OPTION_VALUE || isUpdateRequesting, dismissIntroductionBanner, }; - } ); + }, [] ); }; From 162d790a7afb4385eab63d8407ef70c1e2e530f1 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Sun, 19 Mar 2023 20:16:04 +0800 Subject: [PATCH 16/33] Update option name and value to make it more indicative. --- .../client/marketing/hooks/useIntroductionBanner.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts b/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts index 9a4ff91a292..369f5d14747 100644 --- a/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts +++ b/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts @@ -11,16 +11,16 @@ type UseIntroductionBanner = { dismissIntroductionBanner: () => void; }; -const OPTION_NAME = +const OPTION_NAME_BANNER_DISMISSED = 'woocommerce_marketing_overview_multichannel_banner_dismissed'; -const OPTION_VALUE = 'yes'; +const OPTION_VALUE_YES = 'yes'; export const useIntroductionBanner = (): UseIntroductionBanner => { const { updateOptions } = useDispatch( OPTIONS_STORE_NAME ); const dismissIntroductionBanner = () => { updateOptions( { - [ OPTION_NAME ]: OPTION_VALUE, + [ OPTION_NAME_BANNER_DISMISSED ]: OPTION_VALUE_YES, } ); recordEvent( 'marketing_multichannel_banner_dismissed', {} ); }; @@ -31,9 +31,12 @@ export const useIntroductionBanner = (): UseIntroductionBanner => { const isUpdateRequesting = isOptionsUpdating(); return { - loading: ! hasFinishedResolution( 'getOption', [ OPTION_NAME ] ), + loading: ! hasFinishedResolution( 'getOption', [ + OPTION_NAME_BANNER_DISMISSED, + ] ), isIntroductionBannerDismissed: - getOption( OPTION_NAME ) === OPTION_VALUE || isUpdateRequesting, + getOption( OPTION_NAME_BANNER_DISMISSED ) === + OPTION_VALUE_YES || isUpdateRequesting, dismissIntroductionBanner, }; }, [] ); From 99c6ebff1554b8ed7fd111af20395e9b8c7cb0c1 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Sun, 19 Mar 2023 20:38:20 +0800 Subject: [PATCH 17/33] Remove the use of isOptionsUpdating in useIntroductionBanner. isOptionsUpdating will return true for any option update, not just our option here. This causes issue as shown in demo video in https://github.com/woocommerce/woocommerce/pull/37110#discussion_r1130531104. We can just depend on getOption. When we update an option, it will be updated immediately in wp.data store before making API request to update the option in database (see https://github.com/woocommerce/woocommerce/blob/c5564a15c11eae5b30de7ab6e37edbd973a29ebe/packages/js/data/src/options/actions.ts#L44). --- .../client/marketing/hooks/useIntroductionBanner.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts b/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts index 369f5d14747..5d55c9a41d2 100644 --- a/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts +++ b/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts @@ -26,17 +26,15 @@ export const useIntroductionBanner = (): UseIntroductionBanner => { }; return useSelect( ( select ) => { - const { getOption, isOptionsUpdating, hasFinishedResolution } = + const { getOption, hasFinishedResolution } = select( OPTIONS_STORE_NAME ); - const isUpdateRequesting = isOptionsUpdating(); return { loading: ! hasFinishedResolution( 'getOption', [ OPTION_NAME_BANNER_DISMISSED, ] ), isIntroductionBannerDismissed: - getOption( OPTION_NAME_BANNER_DISMISSED ) === - OPTION_VALUE_YES || isUpdateRequesting, + getOption( OPTION_NAME_BANNER_DISMISSED ) === OPTION_VALUE_YES, dismissIntroductionBanner, }; }, [] ); From 1b65be0a5338f3b235f048fa7da29a42330e3227 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Sun, 19 Mar 2023 20:50:37 +0800 Subject: [PATCH 18/33] Fix useSelect dependency in useIntroductionBanner. --- .../client/marketing/hooks/useIntroductionBanner.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts b/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts index 5d55c9a41d2..0eebcb471a1 100644 --- a/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts +++ b/plugins/woocommerce-admin/client/marketing/hooks/useIntroductionBanner.ts @@ -25,7 +25,7 @@ export const useIntroductionBanner = (): UseIntroductionBanner => { recordEvent( 'marketing_multichannel_banner_dismissed', {} ); }; - return useSelect( ( select ) => { + const { loading, data } = useSelect( ( select ) => { const { getOption, hasFinishedResolution } = select( OPTIONS_STORE_NAME ); @@ -33,9 +33,13 @@ export const useIntroductionBanner = (): UseIntroductionBanner => { loading: ! hasFinishedResolution( 'getOption', [ OPTION_NAME_BANNER_DISMISSED, ] ), - isIntroductionBannerDismissed: - getOption( OPTION_NAME_BANNER_DISMISSED ) === OPTION_VALUE_YES, - dismissIntroductionBanner, + data: getOption( OPTION_NAME_BANNER_DISMISSED ), }; }, [] ); + + return { + loading, + isIntroductionBannerDismissed: data === OPTION_VALUE_YES, + dismissIntroductionBanner, + }; }; From 65523e36dda2f0758e5917e0e275b744a36ea3b1 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Sun, 19 Mar 2023 20:54:34 +0800 Subject: [PATCH 19/33] Fix spacing for close button in IntroductionBanner. --- .../IntroductionBanner/IntroductionBanner.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss index 7c46d7887f5..95209ff6e1f 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss @@ -36,7 +36,7 @@ .woocommerce-marketing-introduction-banner-close-button { position: absolute; - top: $gap-smaller; + top: $gap-small; right: $gap; padding: 0; } From 155211d77ac41caf3143a77f483ee1f43bc227ce Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Sun, 19 Mar 2023 20:56:00 +0800 Subject: [PATCH 20/33] Remove unneeded Icon component. --- .../IntroductionBanner/IntroductionBanner.tsx | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx index 4fb9cfef079..9ff0049ce5c 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx @@ -90,18 +90,11 @@ export const IntroductionBanner = ( { - - } + { { __( 'Built by WooCommerce', 'woocommerce' ) } From 6b75b5db384de2a9c9d9d5c3f2b37a3bc55a5617 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Sun, 19 Mar 2023 20:58:54 +0800 Subject: [PATCH 21/33] Rename variables to make them clearer. --- .../IntroductionBanner/IntroductionBanner.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx index 9ff0049ce5c..38631a83b39 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx @@ -28,7 +28,7 @@ export const IntroductionBanner = ( { onDismiss, onAddChannels, }: IntroductionBannerProps ) => { - const [ open, setOpen ] = useState( false ); + const [ isModalOpen, setModalOpen ] = useState( false ); const { data: dataRegistered } = useRegisteredChannels(); const { data: dataRecommended } = useRecommendedChannels(); @@ -111,7 +111,7 @@ export const IntroductionBanner = ( {
From c6a95ae9bf47ea38a6c9a1fa654a8fd3ee561f0a Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Sun, 19 Mar 2023 21:10:22 +0800 Subject: [PATCH 22/33] Rename callback props in IntroductionBanner to make them clearer. --- .../IntroductionBanner/IntroductionBanner.tsx | 12 ++++++------ .../MarketingOverviewMultichannel.tsx | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx index 38631a83b39..cf3d1cae97e 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx @@ -20,13 +20,13 @@ import illustrationUrl from './illustration.svg'; import illustrationLargeUrl from './illustration-large.svg'; type IntroductionBannerProps = { - onDismiss: () => void; - onAddChannels: () => void; + onDismissClick: () => void; + onAddChannelsClick: () => void; }; export const IntroductionBanner = ( { - onDismiss, - onAddChannels, + onDismissClick, + onAddChannelsClick, }: IntroductionBannerProps ) => { const [ isModalOpen, setModalOpen ] = useState( false ); const { data: dataRegistered } = useRegisteredChannels(); @@ -120,7 +120,7 @@ export const IntroductionBanner = ( { { showAddChannelsButton && ( @@ -137,7 +137,7 @@ export const IntroductionBanner = ( { diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx index 46de03f7709..4b5eb7f21ec 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx @@ -68,8 +68,8 @@ export const MarketingOverviewMultichannel: React.FC = () => {
{ ! isIntroductionBannerDismissed && ( { + onDismissClick={ dismissIntroductionBanner } + onAddChannelsClick={ () => { addChannelsButtonRef.current?.focus(); addChannelsButtonRef.current?.click(); addChannelsButtonRef.current?.scrollIntoView(); From 458c16bad9b88c409e1d0928506582fa9463abfa Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Sun, 19 Mar 2023 22:54:55 +0800 Subject: [PATCH 23/33] Move useCampaigns to shared hooks directory. --- plugins/woocommerce-admin/client/marketing/hooks/index.ts | 1 + .../Campaigns => hooks}/useCampaigns.ts | 0 .../overview-multichannel/Campaigns/Campaigns.test.tsx | 8 ++------ .../overview-multichannel/Campaigns/Campaigns.tsx | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) rename plugins/woocommerce-admin/client/marketing/{overview-multichannel/Campaigns => hooks}/useCampaigns.ts (100%) diff --git a/plugins/woocommerce-admin/client/marketing/hooks/index.ts b/plugins/woocommerce-admin/client/marketing/hooks/index.ts index 459b0938447..3492d275ed0 100644 --- a/plugins/woocommerce-admin/client/marketing/hooks/index.ts +++ b/plugins/woocommerce-admin/client/marketing/hooks/index.ts @@ -3,3 +3,4 @@ export { useInstalledPlugins } from './useInstalledPlugins'; export { useRegisteredChannels } from './useRegisteredChannels'; export { useRecommendedChannels } from './useRecommendedChannels'; export { useCampaignTypes } from './useCampaignTypes'; +export { useCampaigns } from './useCampaigns'; diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/useCampaigns.ts b/plugins/woocommerce-admin/client/marketing/hooks/useCampaigns.ts similarity index 100% rename from plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/useCampaigns.ts rename to plugins/woocommerce-admin/client/marketing/hooks/useCampaigns.ts diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.test.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.test.tsx index 96fd6105337..aaa59396728 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.test.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.test.tsx @@ -7,15 +7,11 @@ import userEvent from '@testing-library/user-event'; /** * Internal dependencies */ -import { useCampaigns } from './useCampaigns'; -import { useCampaignTypes } from '~/marketing/hooks'; +import { useCampaignTypes, useCampaigns } from '~/marketing/hooks'; import { Campaigns } from './Campaigns'; -jest.mock( './useCampaigns', () => ( { - useCampaigns: jest.fn(), -} ) ); - jest.mock( '~/marketing/hooks', () => ( { + useCampaigns: jest.fn(), useCampaignTypes: jest.fn(), } ) ); diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.tsx index 9867a2495b0..d3fdcf71bca 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Campaigns/Campaigns.tsx @@ -28,7 +28,7 @@ import { CardHeaderTitle, CreateNewCampaignModal, } from '~/marketing/components'; -import { useCampaigns } from './useCampaigns'; +import { useCampaigns } from '~/marketing/hooks'; import './Campaigns.scss'; const tableCaption = __( 'Campaigns', 'woocommerce' ); From 11683be1a86fb50dbf4c6f5d7743be72097452cf Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Sun, 19 Mar 2023 23:17:22 +0800 Subject: [PATCH 24/33] Set default parameter values for useCampaigns. --- .../client/marketing/hooks/useCampaigns.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/hooks/useCampaigns.ts b/plugins/woocommerce-admin/client/marketing/hooks/useCampaigns.ts index 01765b61b62..6b1672142b6 100644 --- a/plugins/woocommerce-admin/client/marketing/hooks/useCampaigns.ts +++ b/plugins/woocommerce-admin/client/marketing/hooks/useCampaigns.ts @@ -27,13 +27,10 @@ type UseCampaignsType = { /** * Custom hook to get campaigns. * - * @param page Page number. First page is `1`. - * @param perPage Page size, i.e. number of records in one page. + * @param page Page number. Default is `1`. + * @param perPage Page size, i.e. number of records in one page. Default is `5`. */ -export const useCampaigns = ( - page: number, - perPage: number -): UseCampaignsType => { +export const useCampaigns = ( page = 1, perPage = 5 ): UseCampaignsType => { const { data: channels } = useRegisteredChannels(); return useSelect( From ddd287cc4cfb5c2a8de186c7d6b16f86860da292 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Sun, 19 Mar 2023 23:30:21 +0800 Subject: [PATCH 25/33] Show Campaigns card when banner is dismissed or campaigns total is truthy. --- .../MarketingOverviewMultichannel.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx index 4b5eb7f21ec..efdd1cbd46c 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx @@ -12,6 +12,7 @@ import '~/marketing/data-multichannel'; import { CenteredSpinner } from '~/marketing/components'; import { useIntroductionBanner, + useCampaigns, useRegisteredChannels, useRecommendedChannels, useCampaignTypes, @@ -31,6 +32,7 @@ export const MarketingOverviewMultichannel: React.FC = () => { isIntroductionBannerDismissed, dismissIntroductionBanner, } = useIntroductionBanner(); + const { loading: loadingCampaigns, meta: metaCampaigns } = useCampaigns(); const { loading: loadingCampaignTypes, data: dataCampaignTypes, @@ -48,6 +50,7 @@ export const MarketingOverviewMultichannel: React.FC = () => { if ( loadingIntroductionBanner || + ( loadingCampaigns && metaCampaigns?.total === undefined ) || ( loadingCampaignTypes && ! dataCampaignTypes ) || ( loadingRegistered && ! dataRegistered ) || ( loadingRecommended && ! dataRecommended ) @@ -55,6 +58,10 @@ export const MarketingOverviewMultichannel: React.FC = () => { return ; } + const shouldShowCampaigns = + dataRegistered?.length && + ( isIntroductionBannerDismissed || !! metaCampaigns?.total ); + const shouldShowExtensions = getAdminSetting( 'allowMarketplaceSuggestions', false ) && currentUserCan( 'install_plugins' ); @@ -76,7 +83,7 @@ export const MarketingOverviewMultichannel: React.FC = () => { } } /> ) } - { !! dataRegistered?.length && } + { !! shouldShowCampaigns && } { !! ( dataRegistered && dataRecommended ) && !! ( dataRegistered.length || dataRecommended.length ) && ( Date: Sun, 19 Mar 2023 23:34:17 +0800 Subject: [PATCH 26/33] Remove unneeded CSS. --- .../IntroductionBanner/IntroductionBanner.scss | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss index 95209ff6e1f..66144e3387e 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss @@ -9,15 +9,11 @@ .woocommerce-marketing-introduction-banner-title { font-size: 20px; - font-weight: 400; line-height: 28px; margin-bottom: $gap-smaller; } .woocommerce-marketing-introduction-banner-features { - font-size: 13px; - font-weight: 400; - line-height: 16px; color: $gray-700; svg { @@ -32,7 +28,11 @@ .woocommerce-marketing-introduction-banner-illustration { width: 271px; - background: linear-gradient(90deg, rgba(247, 237, 247, 0) 5.31%, rgba(196, 152, 217, 0.12) 77.75%); + background: linear-gradient( + 90deg, + rgba( 247, 237, 247, 0 ) 5.31%, + rgba( 196, 152, 217, 0.12 ) 77.75% + ); .woocommerce-marketing-introduction-banner-close-button { position: absolute; From 75c11a681db3fe7ee13f1446a4462531db6f8a89 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Mon, 20 Mar 2023 00:11:32 +0800 Subject: [PATCH 27/33] Simplify CSS to have less hardcoded width value. --- .../IntroductionBanner/IntroductionBanner.scss | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss index 66144e3387e..93ee80d5f3c 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss @@ -1,10 +1,11 @@ .woocommerce-marketing-introduction-banner { & > div { display: flex; + flex-wrap: wrap; } .woocommerce-marketing-introduction-banner-content { - width: 350px; + flex: 1 0; margin: 32px 20px 32px 40px; .woocommerce-marketing-introduction-banner-title { @@ -27,12 +28,8 @@ } .woocommerce-marketing-introduction-banner-illustration { - width: 271px; - background: linear-gradient( - 90deg, - rgba( 247, 237, 247, 0 ) 5.31%, - rgba( 196, 152, 217, 0.12 ) 77.75% - ); + flex: 0 0 270px; + background: linear-gradient(90deg, rgba(247, 237, 247, 0) 5.31%, rgba(196, 152, 217, 0.12) 77.75%); .woocommerce-marketing-introduction-banner-close-button { position: absolute; From 5455abcabb31ce7ecf4261711b22cdd4b3959bc9 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Mon, 20 Mar 2023 01:00:19 +0800 Subject: [PATCH 28/33] Use useImperativeHandle instead of exposing button ref in Channels. --- .../Channels/Channels.tsx | 156 ++++++++++-------- .../overview-multichannel/Channels/index.ts | 1 + .../MarketingOverviewMultichannel.tsx | 10 +- 3 files changed, 96 insertions(+), 71 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/Channels.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/Channels.tsx index 37095169b23..5abf9f0d13f 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/Channels.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/Channels.tsx @@ -1,7 +1,13 @@ /** * External dependencies */ -import { Fragment, useState } from '@wordpress/element'; +import { + Fragment, + useState, + forwardRef, + useImperativeHandle, + useRef, +} from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { Card, @@ -27,80 +33,100 @@ import { RegisteredChannelCardBody } from './RegisteredChannelCardBody'; import './Channels.scss'; type ChannelsProps = { - addChannelsButtonRef: React.ForwardedRef< HTMLButtonElement >; registeredChannels: Array< RegisteredChannel >; recommendedChannels: Array< RecommendedChannel >; onInstalledAndActivated?: () => void; }; -export const Channels: React.FC< ChannelsProps > = ( { - addChannelsButtonRef, - registeredChannels, - recommendedChannels, - onInstalledAndActivated, -} ) => { - const hasRegisteredChannels = registeredChannels.length >= 1; - +export type ChannelsRef = { /** - * State to collapse / expand the recommended channels. - * Initial state is expanded if there are no registered channels in first page load. + * Scroll into the "Add channels" section in the card. + * The section will be expanded, and the "Add channels" button will be in focus. */ - const [ expanded, setExpanded ] = useState( ! hasRegisteredChannels ); + scrollIntoAddChannels: () => void; +}; - return ( - - - - { __( 'Channels', 'woocommerce' ) } - - { ! hasRegisteredChannels && ( - - { __( - 'Start by adding a channel to your store', - 'woocommerce' - ) } - - ) } - +export const Channels = forwardRef< ChannelsRef, ChannelsProps >( + ( + { registeredChannels, recommendedChannels, onInstalledAndActivated }, + ref + ) => { + const hasRegisteredChannels = registeredChannels.length >= 1; - { /* Registered channels section. */ } - { registeredChannels.map( ( el, idx ) => { - return ( + /** + * State to collapse / expand the recommended channels. + * Initial state is expanded if there are no registered channels in first page load. + */ + const [ expanded, setExpanded ] = useState( ! hasRegisteredChannels ); + const addChannelsButtonRef = useRef< HTMLButtonElement >( null ); + + useImperativeHandle( + ref, + () => ( { + scrollIntoAddChannels: () => { + setExpanded( true ); + addChannelsButtonRef.current?.focus(); + addChannelsButtonRef.current?.scrollIntoView(); + }, + } ), + [] + ); + + return ( + + + + { __( 'Channels', 'woocommerce' ) } + + { ! hasRegisteredChannels && ( + + { __( + 'Start by adding a channel to your store', + 'woocommerce' + ) } + + ) } + + + { /* Registered channels section. */ } + { registeredChannels.map( ( el, idx ) => ( { idx !== registeredChannels.length - 1 && ( ) } - ); - } ) } + ) ) } - { /* Recommended channels section. */ } - { recommendedChannels.length >= 1 && ( -
- { !! hasRegisteredChannels && ( - <> - - - - - - ) } - { !! expanded && - recommendedChannels.map( ( el, idx ) => { - return ( + > + { __( 'Add channels', 'woocommerce' ) } + + + + + ) } + { !! expanded && + recommendedChannels.map( ( el, idx ) => ( = ( { ) } - ); - } ) } -
- ) } -
- ); -}; + ) ) } +
+ ) } +
+ ); + } +); diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/index.ts b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/index.ts index da0d9c56072..f0e4fcc3762 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/index.ts +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/index.ts @@ -1 +1,2 @@ export { Channels } from './Channels'; +export type { ChannelsRef } from './Channels'; diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx index efdd1cbd46c..3919ab5e482 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx @@ -20,7 +20,7 @@ import { import { getAdminSetting } from '~/utils/admin-settings'; import { IntroductionBanner } from './IntroductionBanner'; import { Campaigns } from './Campaigns'; -import { Channels } from './Channels'; +import { Channels, ChannelsRef } from './Channels'; import { InstalledExtensions } from './InstalledExtensions'; import { DiscoverTools } from './DiscoverTools'; import { LearnMarketing } from './LearnMarketing'; @@ -46,7 +46,7 @@ export const MarketingOverviewMultichannel: React.FC = () => { const { loading: loadingRecommended, data: dataRecommended } = useRecommendedChannels(); const { currentUserCan } = useUser(); - const addChannelsButtonRef = useRef< HTMLButtonElement >( null ); + const channelsRef = useRef< ChannelsRef >( null ); if ( loadingIntroductionBanner || @@ -77,9 +77,7 @@ export const MarketingOverviewMultichannel: React.FC = () => { { - addChannelsButtonRef.current?.focus(); - addChannelsButtonRef.current?.click(); - addChannelsButtonRef.current?.scrollIntoView(); + channelsRef.current?.scrollIntoAddChannels(); } } /> ) } @@ -87,7 +85,7 @@ export const MarketingOverviewMultichannel: React.FC = () => { { !! ( dataRegistered && dataRecommended ) && !! ( dataRegistered.length || dataRecommended.length ) && ( Date: Mon, 20 Mar 2023 17:23:20 +0800 Subject: [PATCH 29/33] Make shouldShowCampaigns boolean type. --- .../MarketingOverviewMultichannel.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx index 3919ab5e482..94784f01468 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/MarketingOverviewMultichannel.tsx @@ -58,9 +58,10 @@ export const MarketingOverviewMultichannel: React.FC = () => { return ; } - const shouldShowCampaigns = + const shouldShowCampaigns = !! ( dataRegistered?.length && - ( isIntroductionBannerDismissed || !! metaCampaigns?.total ); + ( isIntroductionBannerDismissed || metaCampaigns?.total ) + ); const shouldShowExtensions = getAdminSetting( 'allowMarketplaceSuggestions', false ) && @@ -81,7 +82,7 @@ export const MarketingOverviewMultichannel: React.FC = () => { } } /> ) } - { !! shouldShowCampaigns && } + { shouldShowCampaigns && } { !! ( dataRegistered && dataRecommended ) && !! ( dataRegistered.length || dataRecommended.length ) && ( Date: Mon, 20 Mar 2023 17:46:54 +0800 Subject: [PATCH 30/33] Make scrollIntoView center on the "Add channels" button. --- .../marketing/overview-multichannel/Channels/Channels.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/Channels.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/Channels.tsx index 5abf9f0d13f..7427f3f15f1 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/Channels.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/Channels/Channels.tsx @@ -66,7 +66,9 @@ export const Channels = forwardRef< ChannelsRef, ChannelsProps >( scrollIntoAddChannels: () => { setExpanded( true ); addChannelsButtonRef.current?.focus(); - addChannelsButtonRef.current?.scrollIntoView(); + addChannelsButtonRef.current?.scrollIntoView( { + block: 'center', + } ); }, } ), [] From 4e38969ce7d2f3b1246573fac46c4eb7b4d3b9af Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Mon, 20 Mar 2023 18:07:30 +0800 Subject: [PATCH 31/33] Use one illustration instead of two in IntroductionBanner. --- .../IntroductionBanner/IntroductionBanner.scss | 9 ++++++++- .../IntroductionBanner/IntroductionBanner.tsx | 16 +++++----------- .../IntroductionBanner/illustration-large.svg | 5 ----- 3 files changed, 13 insertions(+), 17 deletions(-) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss index 93ee80d5f3c..99ac6dc8ad4 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.scss @@ -29,7 +29,14 @@ .woocommerce-marketing-introduction-banner-illustration { flex: 0 0 270px; - background: linear-gradient(90deg, rgba(247, 237, 247, 0) 5.31%, rgba(196, 152, 217, 0.12) 77.75%); + background: linear-gradient(90deg, rgba(247, 237, 247, 0) 5.31%, rgba(196, 152, 217, 0.12) 77.75%), + linear-gradient(90deg, rgba(247, 237, 247, 0) 22%, rgba(196, 152, 217, 0.12) 84.6%); + + .woocommerce-marketing-introduction-banner-image-placeholder { + width: 100%; + height: 100%; + background: center / contain no-repeat; + } .woocommerce-marketing-introduction-banner-close-button { position: absolute; diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx index cf3d1cae97e..8c470ec627f 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx @@ -16,7 +16,6 @@ import { } from '~/marketing/hooks'; import './IntroductionBanner.scss'; import wooIconUrl from './woo.svg'; -import illustrationUrl from './illustration.svg'; import illustrationLargeUrl from './illustration-large.svg'; type IntroductionBannerProps = { @@ -141,16 +140,11 @@ export const IntroductionBanner = ( { > - {
diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration-large.svg b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration-large.svg index 0bd6ed50302..3a00d63416c 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration-large.svg +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration-large.svg @@ -1,6 +1,5 @@ - @@ -62,10 +61,6 @@ - - - - From 0300078dfdd52eccf3cce3eb4650986f9e895439 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Mon, 20 Mar 2023 18:08:30 +0800 Subject: [PATCH 32/33] Remove unused illustration.svg file. --- .../IntroductionBanner/illustration.svg | 73 ------------------- 1 file changed, 73 deletions(-) delete mode 100644 plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration.svg diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration.svg b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration.svg deleted file mode 100644 index b2834e68fb8..00000000000 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration.svg +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From a2b02fc00c044cd8d59a01f7e28fd53b73279d92 Mon Sep 17 00:00:00 2001 From: Gan Eng Chin Date: Mon, 20 Mar 2023 18:11:02 +0800 Subject: [PATCH 33/33] Rename illustration-large.svg to illustration.svg. --- .../IntroductionBanner/IntroductionBanner.tsx | 4 ++-- .../{illustration-large.svg => illustration.svg} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/{illustration-large.svg => illustration.svg} (100%) diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx index 8c470ec627f..829152f03dd 100644 --- a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx +++ b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/IntroductionBanner.tsx @@ -16,7 +16,7 @@ import { } from '~/marketing/hooks'; import './IntroductionBanner.scss'; import wooIconUrl from './woo.svg'; -import illustrationLargeUrl from './illustration-large.svg'; +import illustrationUrl from './illustration.svg'; type IntroductionBannerProps = { onDismissClick: () => void; @@ -143,7 +143,7 @@ export const IntroductionBanner = ( {
diff --git a/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration-large.svg b/plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration.svg similarity index 100% rename from plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration-large.svg rename to plugins/woocommerce-admin/client/marketing/overview-multichannel/IntroductionBanner/illustration.svg