Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Onboarding: Create new ads account. #2651

Open
wants to merge 36 commits into
base: update/2582-claim-ads-account
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
5b64b6b
Create new ads account.
ankitrox Oct 25, 2024
fdccdfb
Fix: lint css.
ankitrox Oct 25, 2024
ab8984e
Merge branch 'update/2596-connect-ads-account' into update/2603-creat…
ankitrox Oct 28, 2024
d4e0142
Add css.
ankitrox Oct 28, 2024
1584e33
Do not show card if account is in unclaimed status.
ankitrox Oct 28, 2024
a00d42c
Merge branch 'update/2596-connect-ads-account' into update/2603-creat…
ankitrox Oct 28, 2024
54fdfc8
Add E2E tests.
ankitrox Oct 28, 2024
3b25965
Fix: E2E issues.
ankitrox Oct 29, 2024
86a174e
Resolve conflicts in E2E.
ankitrox Oct 29, 2024
e1fca96
Resolve conflicts.
ankitrox Oct 29, 2024
073b04f
CR feedback.
ankitrox Oct 29, 2024
863a71c
Resolve conflicts.
ankitrox Oct 29, 2024
e9a071b
Merge branch 'update/2596-connect-ads-account' into update/2603-creat…
ankitrox Oct 29, 2024
3e2dcbe
Show correct text when creating an account.
asvinb Oct 30, 2024
db10842
Revert change.
asvinb Oct 30, 2024
3e4249c
Prevent complete re rendering of the card.
asvinb Oct 30, 2024
0c3f1c7
Merge branch 'update/2582-claim-ads-account' into update/2603-create-…
asvinb Oct 30, 2024
f31dcc4
Fix error.
asvinb Oct 30, 2024
46aef1c
Fetch existing accounts again.
asvinb Oct 30, 2024
b93f3aa
Display updating text only when clicking the claim button.
asvinb Oct 30, 2024
d3dae92
Save WIP.
asvinb Oct 31, 2024
9f335dd
Merge branch 'feature/2509-consolidate-google-account-cards' into upd…
asvinb Oct 31, 2024
3c19aa9
Save WIP.
asvinb Oct 31, 2024
90db787
UX improvements.
asvinb Nov 4, 2024
797ea87
Review comments.
asvinb Nov 4, 2024
74ff220
Use single quotes.
asvinb Nov 4, 2024
e6222de
Merge branch 'update/2582-claim-ads-account' into update/2603-create-…
asvinb Nov 4, 2024
2d9c2cf
Use correct class name.
asvinb Nov 4, 2024
5638687
Improve 'Connect Google account' E2E tests
joemcgill Nov 4, 2024
6bb4318
Update title and indicator label.
asvinb Nov 5, 2024
d46d6ca
Merge branch 'update/2603-create-ads-account' of github.com:woocommer…
asvinb Nov 5, 2024
50e36fd
Merge branch 'update/2582-claim-ads-account' into update/2603-create-…
asvinb Nov 5, 2024
75c7827
Merge branch 'update/2582-claim-ads-account' into update/2603-create-…
asvinb Nov 6, 2024
fea64c6
Address CR feedback.
asvinb Nov 6, 2024
92fb813
Merge branch 'update/2582-claim-ads-account' into update/2603-create-…
asvinb Nov 6, 2024
01f1097
Merge branch 'update/2582-claim-ads-account' into update/2603-create-…
joemcgill Nov 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion js/src/components/account-card/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ const appearanceDict = {
// The `center` is the default alignment, and no need to append any additional class name.
const alignStyleName = {
center: false,
top: `gla-account-card__styled--align-top`,
top: 'gla-account-card__styled--align-top',
};

const indicatorAlignStyleName = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import AppModal from '.~/components/app-modal';
import AppButton from '.~/components/app-button';
import WarningIcon from '.~/components/warning-icon';
import './confirm-create-modal.scss';

/**
* Google Ads account creation confirmation modal.
* This modal is shown when the user tries to create a new Google Ads account.
*
* @param {Object} props Component props.
* @param {Function} props.onContinue Callback to continue with account creation.
* @param {Function} props.onRequestClose Callback to close the modal.
* @return {JSX.Element} Confirmation modal.
*/
const ConfirmCreateModal = ( { onContinue, onRequestClose } ) => {
return (
<AppModal
className="gla-ads-warning-modal"
title={ __(
'Create Google Ads Account',
'google-listings-and-ads'
) }
buttons={ [
<AppButton key="confirm" isSecondary onClick={ onContinue }>
{ __(
'Yes, I want a new account',
'google-listings-and-ads'
) }
</AppButton>,
<AppButton key="cancel" isPrimary onClick={ onRequestClose }>
{ __( 'Cancel', 'google-listings-and-ads' ) }
</AppButton>,
] }
onRequestClose={ onRequestClose }
>
<p className="gla-ads-warning-modal__warning-text">
<WarningIcon />
<span>
{ __(
'Are you sure you want to create a new Google Ads account?',
'google-listings-and-ads'
) }
</span>
</p>
<p>
{ __(
'You already have another Ads account associated with this Google account.',
'google-listings-and-ads'
) }
</p>
<p>
{ __(
'If you create a new Google Ads account, you will need to accept an invite to the account before it can be used.',
'google-listings-and-ads'
) }
</p>
</AppModal>
);
};

export default ConfirmCreateModal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.gla-ads-warning-modal {

.gla-ads-warning-modal__warning-text {
display: flex;
align-items: center;
gap: calc(var(--main-gap) / 3);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,17 @@ import DisconnectAccount from '.~/components/google-ads-account-card/disconnect-
*
* @param {Object} props Props.
* @param {boolean} props.isConnected Whether the account is connected.
* @param {Function} props.onCreateNew Callback to create a new account.
* @param {Object} props.restProps Rest props. Passed to AppButton.
* @return {JSX.Element} Footer component.
*/
const ConnectAdsFooter = ( { isConnected, ...restProps } ) => {
// If the account is connected, show the disconnect button.
const ConnectAdsFooter = ( { isConnected, onCreateNew, ...restProps } ) => {
if ( isConnected ) {
return <DisconnectAccount />;
}

return (
<AppButton isTertiary { ...restProps }>
<AppButton isTertiary onClick={ onCreateNew } { ...restProps }>
{ __(
'Or, create a new Google Ads account',
'google-listings-and-ads'
Expand Down
140 changes: 104 additions & 36 deletions js/src/components/google-combo-account-card/connect-ads/connect-ads.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,62 @@ import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import AccountCard from '.~/components/account-card';
import ConnectAdsFooter from './connect-ads-footer';
import ConfirmCreateModal from './confirm-create-modal';
import LoadingLabel from '.~/components/loading-label';
import useApiFetchCallback from '.~/hooks/useApiFetchCallback';
import useDispatchCoreNotices from '.~/hooks/useDispatchCoreNotices';
import useExistingGoogleAdsAccounts from '.~/hooks/useExistingGoogleAdsAccounts';
import useGoogleAdsAccount from '.~/hooks/useGoogleAdsAccount';
import { useAppDispatch } from '.~/data';
import useGoogleAdsAccountReady from '.~/hooks/useGoogleAdsAccountReady';
import AccountCard from '.~/components/account-card';
import AdsAccountSelectControl from '.~/components/ads-account-select-control';
import ConnectedIconLabel from '.~/components/connected-icon-label';
import ConnectAdsFooter from './connect-ads-footer';
import LoadingLabel from '.~/components/loading-label';
import ConnectButton from '.~/components/google-ads-account-card/connect-ads/connect-button';

/**
* ConnectAds component renders an account card to connect to an existing Google Ads account.
*
* @param {Object} props Component props.
* @param {boolean} props.isConnecting Whether the user is in the process of finalizing the Ads account creation, i.e after the user has claimed the account and the step is conversion_action.
* @param {boolean} props.isCreating Whether the user is in the process of creating a new Ads account.
* @param {Function} props.onCreate A callback to fire when creating a new account.
* @return {JSX.Element} {@link AccountCard} filled with content.
*/
const ConnectAds = () => {
const ConnectAds = ( { isConnecting, isCreating, onCreate } ) => {
const [ value, setValue ] = useState();
const [ isLoading, setLoading ] = useState( false );
const { refetchGoogleAdsAccount } = useGoogleAdsAccount();
const { createNotice } = useDispatchCoreNotices();
const { fetchGoogleAdsAccountStatus } = useAppDispatch();
const isConnected = useGoogleAdsAccountReady();
const { googleAdsAccount, hasFinishedResolution } = useGoogleAdsAccount();
const [ showCreateNewModal, setShowCreateNewModal ] = useState( false );
const { existingAccounts: accounts, hasFinishedResolution } =
useExistingGoogleAdsAccounts();
const {
googleAdsAccount,
refetchGoogleAdsAccount,
hasFinishedResolution: hasResolvedGoogleAdsAccount,
} = useGoogleAdsAccount();
const [ connectGoogleAdsAccount ] = useApiFetchCallback( {
path: '/wc/gla/ads/accounts',
method: 'POST',
data: { id: value },
} );

const onCreateNew = () => {
setShowCreateNewModal( true );
};

const handleOnRequestClose = () => {
setShowCreateNewModal( false );
};

const handleOnContinue = async () => {
setShowCreateNewModal( false );
await onCreate();
};

useEffect( () => {
if ( isConnected ) {
setValue( googleAdsAccount.id );
Expand All @@ -53,22 +78,26 @@ const ConnectAds = () => {
try {
await connectGoogleAdsAccount();
await fetchGoogleAdsAccountStatus();
await refetchGoogleAdsAccount();
setLoading( false );
refetchGoogleAdsAccount();
} catch ( error ) {
setLoading( false );
createNotice(
'error',
__(
'Unable to connect your Google Ads account. Please try again later.',
'google-listings-and-ads'
)
);
} finally {
setLoading( false );
}
};

if ( ! accounts?.length ) {
return null;
}

const getIndicator = () => {
if ( ! hasFinishedResolution ) {
if ( ! hasFinishedResolution || ! hasResolvedGoogleAdsAccount ) {
return <LoadingLabel />;
}

Expand All @@ -89,34 +118,73 @@ const ConnectAds = () => {
);
};

return (
<AccountCard
className="gla-google-combo-account-card gla-google-combo-service-account-card--ads"
title={ __(
'Connect to existing Google Ads account',
'google-listings-and-ads'
) }
helper={ __(
'Required to set up conversion measurement for your store.',
// Show a loading state if the Ads account is being updated or if a new Ads account is being created.
if ( isConnecting || isCreating ) {
let title = __(
'Creating a new Google Ads account',
'google-listings-and-ads'
);
let indicatorLabel = __( 'Creating…', 'google-listings-and-ads' );

if ( isConnecting ) {
title = __(
'Connecting your Google Ads account',
'google-listings-and-ads'
) }
alignIndicator="toDetail"
indicator={ getIndicator() }
detail={
<AdsAccountSelectControl
value={ value }
onChange={ setValue }
autoSelectFirstOption
nonInteractive={ isConnected }
/>
}
actions={
<ConnectAdsFooter
isConnected={ isConnected }
disabled={ isLoading }
);
indicatorLabel = __( 'Connecting…', 'google-listings-and-ads' );
}

return (
<AccountCard
className="gla-google-combo-service-account-card--ads"
title={ title }
helper={ __(
'This may take a few minutes, please wait a moment…',
'google-listings-and-ads'
) }
indicator={ <LoadingLabel text={ indicatorLabel } /> }
/>
);
}

return (
<>
<AccountCard
className="gla-google-combo-account-card gla-google-combo-service-account-card--ads"
title={ __(
'Connect to existing Google Ads account',
'google-listings-and-ads'
) }
helper={ __(
'Required to set up conversion measurement for your store.',
'google-listings-and-ads'
) }
alignIndicator="toDetail"
indicator={ getIndicator() }
detail={
<AdsAccountSelectControl
value={ value }
onChange={ setValue }
autoSelectFirstOption
nonInteractive={ isConnected }
/>
}
actions={
<ConnectAdsFooter
disabled={ isLoading }
isConnected={ isConnected }
onCreateNew={ onCreateNew }
/>
}
/>

{ showCreateNewModal && (
<ConfirmCreateModal
onContinue={ handleOnContinue }
onRequestClose={ handleOnRequestClose }
/>
}
/>
) }
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const ConnectedGoogleComboAccountCard = () => {
const { invalidateResolution } = useAppDispatch();
const { googleAdsAccount } = useGoogleAdsAccount();
const { hasAccess, step } = useGoogleAdsAccountStatus();
const [ upsertAdsAccount ] = useUpsertAdsAccount();
const [ upsertAdsAccount, { action } ] = useUpsertAdsAccount();

const finalizeAdsAccountCreation =
hasAccess === true && step === 'conversion_action';
Expand Down Expand Up @@ -104,8 +104,9 @@ const ConnectedGoogleComboAccountCard = () => {

const hasExistingGoogleAdsAccounts = existingGoogleAdsAccounts?.length > 0;
const showConnectAds =
( editMode && hasExistingGoogleAdsAccounts ) ||
( ! isConnected && hasExistingGoogleAdsAccounts );
( ( editMode && hasExistingGoogleAdsAccounts ) ||
( ! isConnected && hasExistingGoogleAdsAccounts ) ) &&
! shouldClaimGoogleAdsAccount;

// Show the spinner if there's an account creation in progress and account should not be claimed.
// If we are not showing the ConnectMC screen, for e.g when we are creating the first account,
Expand All @@ -132,7 +133,13 @@ const ConnectedGoogleComboAccountCard = () => {
/>
</AccountCard>

{ showConnectAds && <ConnectAds /> }
{ showConnectAds && (
<ConnectAds
isConnecting={ action === 'update' }
isCreating={ action === 'create' }
onCreate={ upsertAdsAccount }
/>
) }

{ showConnectMC && (
<ConnectMC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,9 @@
&:empty {
display: none;
}

.gla-ads-conversion-measurement-notice {
margin-bottom: calc((var(--large-gap)) / 2);
}
}
}
Loading