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

Free Listings + Paid Ads: Add the product feed status section UI #1638

Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
18 changes: 18 additions & 0 deletions js/src/data/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,24 @@ export function handleFetchError( error, message ) {
* @property {boolean} [contact_info_visible] Whether the phone number, email, and/or address are visible on the website.
*/

/**
* @typedef {Object} ProductStatisticsDetails
* @property {number} active Number of active products.
* @property {number} expiring Number of expiring products.
* @property {number} pending Number of pending products.
* @property {number} disapproved Number of disapproved products.
* @property {number} not_synced Number of not synced products.
*/

/**
* Product status statistics on Google Merchant Center
*
* @typedef {Object} ProductStatistics
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💅 Since the type of ProductStatistics is defined, it would be nice to add some doc comments in the below function that is using this type.

export function* receiveMCProductStatistics( mcProductStatistics ) {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in 4566683.

* @property {number} scheduled_sync Number of scheduled jobs which will sync products to Google.
* @property {number} timestamp Timestamp reflecting when the product status statistics were last generated.
* @property {ProductStatisticsDetails} statistics Statistics information of product status on Google Merchant Center.
*/

/**
*
* @return {Array<ShippingRate>} Array of individual shipping rates.
Expand Down
20 changes: 7 additions & 13 deletions js/src/product-feed/product-statistics/status-box/sync-status.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,17 @@ import Status from '.~/product-feed/product-statistics/status-box/status';
import { glaData } from '.~/constants';
import SyncIcon from '.~/components/sync-icon';
import SuccessIcon from '.~/components/success-icon';
import getNumberOfSyncProducts from '.~/utils/getNumberOfSyncProducts';

/**
* @typedef {import('.~/data/actions').ProductStatistics } ProductStatistics
*/

/**
* Returns the text as well as the icon an description for the Sync Status
* based on the `scheduled_sync` value as the synced number of products.
*
* @param {Object} data Data with the sync information
* @param {number} data.scheduled_sync Amount of scheduled jobs which will sync products to Google.
* @param {Object} data.statistics Merchant Center product status statistics information.
* @param {number} data.timestamp Timestamp reflecting when the product status statistics were last generated.
* @param {ProductStatistics} data Product status statistics on Google Merchant Center
* @return {Object} The icon, status and description of the sync process.
*/
function getSyncResult( {
Expand All @@ -36,15 +38,7 @@ function getSyncResult( {
};
}

const totalSynced = Object.entries( statistics ).reduce(
( sum, [ key, num ] ) => {
if ( key === 'not_synced' ) {
return sum;
}
return sum + num;
},
0
);
const totalSynced = getNumberOfSyncProducts( statistics );

return {
Icon: SuccessIcon,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/**
* External dependencies
*/
import { sprintf, __, _n } from '@wordpress/i18n';
import { Flex, FlexItem, FlexBlock } from '@wordpress/components';

/**
* Internal dependencies
*/
import Section from '.~/wcdl/section';
import AppDocumentationLink from '.~/components/app-documentation-link';
import SyncIcon from '.~/components/sync-icon';
import AppTooltip from '.~/components/app-tooltip';
import getNumberOfSyncProducts from '.~/utils/getNumberOfSyncProducts';
import './product-feed-status-section.scss';

function ProductQuantity( { quantity } ) {
if ( ! Number.isInteger( quantity ) ) {
return null;
}

const text = sprintf(
// translators: %d: number of products will be synced to Google Merchant Center.
_n( '%d product', '%d products', quantity, 'google-listings-and-ads' ),
quantity
);

return (
<>
<span className="gla-product-feed-status-section__product-quantity-separator" />
<AppTooltip
className
position="top center"
text={ __(
'You can manage and edit your product feed after this setup',
'google-listings-and-ads'
) }
>
{ text }
</AppTooltip>
</>
);
}

// TODO: `href`` is not yet ready. Will be added later.
/**
* @fires gla_documentation_link_click with `{ context: 'setup-paid-ads', link_id: 'product-feed-status-learn-more', href: 'https://example.com' }`
*/

/**
* Renders a section layout to elaborate on how the product listings will be processed
* and show the number of products will be synced to Google Merchant Center.
*/
export default function ProductFeedStatusSection() {
/*
const { data, hasFinishedResolution } = useAppSelectDispatch(
'getMCProductStatistics'
);
*/
// TODO: Replace the dummy data with the above code later to use the adjusted API.
Comment on lines +55 to +60
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❔ Just wanted to make sure my understanding is right. The API mc/product-statistics would only be returning data after we call mc/settings/sync, so the comment Replace the dummy data with the above code later to use the adjusted API. means we would make a POST request to mc/settings/sync later, right?

Copy link
Member Author

@eason9487 eason9487 Aug 18, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, as per my test from the frontend side, it has to call mc/settings/sync before getting statistics from mc/product-statistics, so the frontend side will call mc/settings/sync when entering step 4. And the mc/product-statistics seems to check whether the MC_SETUP_COMPLETED_AT flag is set before returning, thus, we will need the related adjustment in this project as well.

const data = {
statistics: {
active: 1,
expiring: 2,
pending: 3,
disapproved: 4,
not_synced: 5,
},
};
const hasFinishedResolution = true;
const productQuantity = hasFinishedResolution
? getNumberOfSyncProducts( data.statistics )
: null;

return (
<Section
className="gla-product-feed-status-section"
title={ __( 'Product feed status', 'google-listings-and-ads' ) }
description={
<AppDocumentationLink
context="setup-paid-ads"
linkId="product-feed-status-learn-more"
href="https://example.com" // TODO: Not yet ready. Will be added later.
>
{ __( 'Learn more', 'google-listings-and-ads' ) }
</AppDocumentationLink>
}
>
<Section.Card>
<Section.Card.Body>
<Flex align="flex-start" gap={ 3 }>
<FlexItem>
<SyncIcon />
</FlexItem>
<FlexBlock>
<Section.Card.Title>
{ __(
'Your product listings are being uploaded',
'google-listings-and-ads'
) }
<ProductQuantity quantity={ productQuantity } />
</Section.Card.Title>
{ __(
'Google will review your product listings within 3-5 days. Once approved, your products will automatically be live and searchable on Google. You’ll be notified if there are any product feed issues.',
'google-listings-and-ads'
) }
</FlexBlock>
</Flex>
</Section.Card.Body>
</Section.Card>
</Section>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.gla-product-feed-status-section {
.gla-sync-icon {
fill: $gla-color-green;
transform: rotateZ(90deg);
}

.wcdl-subsection-title {
display: flex;
align-items: center;
}

&__product-quantity-separator,
.app-tooltip__children-container {
font-size: $gla-font-smallest;
font-weight: normal;
color: $gray-700;
}

&__product-quantity-separator::before {
content: "•";
display: inline-block;
margin: 0 $grid-unit-10;
}

.app-tooltip__children-container {
padding-bottom: calc($grid-unit-05 / 2);
line-height: 1;
border-bottom: $border-width dashed $gray-600;
}

.components-popover__content {
width: 200px;
white-space: normal;
font-weight: normal;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import StepContentHeader from '.~/components/stepper/step-content-header';
import StepContentFooter from '.~/components/stepper/step-content-footer';
import FaqsSection from '.~/components/paid-ads/faqs-section';
import AppButton from '.~/components/app-button';
import ProductFeedStatusSection from './product-feed-status-section';
import { getProductFeedUrl } from '.~/utils/urls';
import { GUIDE_NAMES } from '.~/constants';
import { API_NAMESPACE } from '.~/data/constants';
Expand Down Expand Up @@ -67,6 +68,7 @@ export default function SetupPaidAds() {
'google-listings-and-ads'
) }
/>
<ProductFeedStatusSection />
<FaqsSection />
<StepContentFooter>
<Flex justify="right" gap={ 4 }>
Expand Down
18 changes: 18 additions & 0 deletions js/src/utils/getNumberOfSyncProducts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* @typedef {import('.~/data/actions').ProductStatisticsDetails } ProductStatisticsDetails
*/

/**
* Return the total number of syncing/synced products except for the `not_synced` category.
*
* @param {ProductStatisticsDetails} statistics The statistics data of scheduled synchronized products.
* @return {number} Number of syncing/synced products.
*/
export default function getNumberOfSyncProducts( statistics ) {
return Object.entries( statistics ).reduce( ( sum, [ key, num ] ) => {
if ( key === 'not_synced' ) {
return sum;
}
return sum + num;
}, 0 );
}